diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 0d2d9043f9b796f75cc9c18995bc57bd2ea765d7..c909fe9e708ed714707552f7bcefe2a206fe8b69 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -7,7 +7,7 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.31 1997/12/20 18:36:26 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.32 1998/01/15 19:41:35 pgsql Exp $
 #
 # NOTES
 #    Essentially all Postgres make files include this file and use the 
@@ -206,7 +206,7 @@ YFLAGS= @YFLAGS@
 YACC= @YACC@
 LEX= @LEX@
 AROPT= @AROPT@
-CFLAGS= -I$(SRCDIR)/include @CPPFLAGS@ @CFLAGS@ 
+CFLAGS= -I$(SRCDIR)/include -I$(SRCDIR)/backend @CPPFLAGS@ @CFLAGS@ 
 CFLAGS_SL= @SHARED_LIB@
 LDFLAGS= @LDFLAGS@ @LIBS@
 DLSUFFIX= @DLSUFFIX@
diff --git a/src/backend/access/common/Makefile b/src/backend/access/common/Makefile
index cf61311f553df950951f00efff2adb0ee8ff0e5c..594ec514db0883ef4e106a1d333d19c577e5fb02 100644
--- a/src/backend/access/common/Makefile
+++ b/src/backend/access/common/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for access/common
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/access/common/Makefile,v 1.8 1997/12/20 00:22:11 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/backend/access/common/Makefile,v 1.9 1998/01/15 19:41:42 pgsql Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -23,7 +23,7 @@ all: SUBSYS.o
 SUBSYS.o: $(OBJS)
 	$(LD) -r -o SUBSYS.o $(OBJS)
 
-heapvalid.o tupdesc.o: ../../fmgr.h
+heaptuple.o heapvalid.o tupdesc.o: ../../fmgr.h
 
 ../../fmgr.h:
 	$(MAKE) -C ../.. fmgr.h
diff --git a/src/backend/access/common/indexvalid.c b/src/backend/access/common/indexvalid.c
index 5a9f351568cdc0455c73f08b23c166970a971685..81240d2c443fd16618fc8c75f50f7e851924526c 100644
--- a/src/backend/access/common/indexvalid.c
+++ b/src/backend/access/common/indexvalid.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.16 1997/09/08 02:19:55 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.17 1998/01/15 19:41:44 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -66,13 +66,13 @@ index_keytest(IndexTuple tuple,
 
 		if (key[0].sk_flags & SK_COMMUTE)
 		{
-			test = (*(key[0].sk_func))
+			test = (*(fmgr_faddr(&key[0].sk_func)))
 				(DatumGetPointer(key[0].sk_argument),
 				 datum) ? 1 : 0;
 		}
 		else
 		{
-			test = (*(key[0].sk_func))
+			test = (*(fmgr_faddr(&key[0].sk_func)))
 				(datum,
 				 DatumGetPointer(key[0].sk_argument)) ? 1 : 0;
 		}
diff --git a/src/backend/access/common/scankey.c b/src/backend/access/common/scankey.c
index 9fbe264ae5c864fbdd00ce69937e4562f180b987..130a80ae6d389c3cbca89c865c5d144f72e56d1e 100644
--- a/src/backend/access/common/scankey.c
+++ b/src/backend/access/common/scankey.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.10 1997/09/07 04:37:39 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.11 1998/01/15 19:41:46 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -61,7 +61,8 @@ ScanKeyEntryInitialize(ScanKey entry,
 	entry->sk_attno = attributeNumber;
 	entry->sk_procedure = procedure;
 	entry->sk_argument = argument;
-	fmgr_info(procedure, &entry->sk_func, &entry->sk_nargs);
+	fmgr_info(procedure, &entry->sk_func);
+	entry->sk_nargs = entry->sk_func.fn_nargs;
 
 	Assert(ScanKeyEntryIsLegal(entry));
 }
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index b247a93ed39b3e3e19da2009ad7c185d1647c72c..a510dc8b203d7cab5459feb794fa577154d62452 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -565,10 +565,10 @@ gistAdjustKeys(Relation r,
 	ev1p = &((GISTENTRY *) VARDATA(evec))[1];
 
 	/* form union of decompressed entries */
-	datum = (char *) (giststate->unionFn) (evec, &datumsize);
+	datum = (*fmgr_faddr(&giststate->unionFn)) (evec, &datumsize);
 
 	/* did union leave decompressed version of oldud unchanged? */
-	(giststate->equalFn) (ev0p->pred, datum, &result);
+	(*fmgr_faddr(&giststate->equalFn)) (ev0p->pred, datum, &result);
 	if (!result)
 	{
 		TupleDesc	td = RelationGetTupleDescriptor(r);
@@ -743,7 +743,7 @@ gistSplit(Relation r,
 	VARSIZE(entryvec) = (maxoff + 2) * sizeof(GISTENTRY) + VARHDRSZ;
 
 	/* now let the user-defined picksplit function set up the split vector */
-	(giststate->picksplitFn) (entryvec, &v);
+	(*fmgr_faddr(&giststate->picksplitFn)) (entryvec, &v);
 
 	/* compress ldatum and rdatum */
 	gistcentryinit(giststate, &tmpentry, v.spl_ldatum, (Relation) NULL,
@@ -1072,7 +1072,7 @@ gistchoose(Relation r, Page p, IndexTuple it,	/* it has compressed entry */
 		size = IndexTupleSize(datum) - sizeof(IndexTupleData);
 		datum += sizeof(IndexTupleData);
 		gistdentryinit(giststate, &entry, datum, r, p, i, size, FALSE);
-		(giststate->penaltyFn) (&entry, &identry, &usize);
+		(*fmgr_faddr(&giststate->penaltyFn)) (&entry, &identry, &usize);
 		if (which_grow < 0 || usize < which_grow)
 		{
 			which = i;
@@ -1150,8 +1150,6 @@ initGISTstate(GISTSTATE *giststate, Relation index)
 	RegProcedure penalty_proc,
 				picksplit_proc,
 				equal_proc;
-	func_ptr	user_fn;
-	int			pronargs;
 	HeapTuple	htup;
 	IndexTupleForm itupform;
 
@@ -1162,20 +1160,13 @@ initGISTstate(GISTSTATE *giststate, Relation index)
 	penalty_proc = index_getprocid(index, 1, GIST_PENALTY_PROC);
 	picksplit_proc = index_getprocid(index, 1, GIST_PICKSPLIT_PROC);
 	equal_proc = index_getprocid(index, 1, GIST_EQUAL_PROC);
-	fmgr_info(consistent_proc, &user_fn, &pronargs);
-	giststate->consistentFn = user_fn;
-	fmgr_info(union_proc, &user_fn, &pronargs);
-	giststate->unionFn = user_fn;
-	fmgr_info(compress_proc, &user_fn, &pronargs);
-	giststate->compressFn = user_fn;
-	fmgr_info(decompress_proc, &user_fn, &pronargs);
-	giststate->decompressFn = user_fn;
-	fmgr_info(penalty_proc, &user_fn, &pronargs);
-	giststate->penaltyFn = user_fn;
-	fmgr_info(picksplit_proc, &user_fn, &pronargs);
-	giststate->picksplitFn = user_fn;
-	fmgr_info(equal_proc, &user_fn, &pronargs);
-	giststate->equalFn = user_fn;
+	fmgr_info(consistent_proc, &giststate->consistentFn);
+	fmgr_info(union_proc, &giststate->unionFn);
+	fmgr_info(compress_proc, &giststate->compressFn);
+	fmgr_info(decompress_proc, &giststate->decompressFn);
+	fmgr_info(penalty_proc, &giststate->penaltyFn);
+	fmgr_info(picksplit_proc, &giststate->picksplitFn);
+	fmgr_info(equal_proc, &giststate->equalFn);
 
 	/* see if key type is different from type of attribute being indexed */
 	htup = SearchSysCacheTuple(INDEXRELID, ObjectIdGetDatum(index->rd_id),
@@ -1259,7 +1250,7 @@ gistdentryinit(GISTSTATE *giststate, GISTENTRY *e, char *pr, Relation r,
 	gistentryinit(*e, pr, r, pg, o, b, l);
 	if (giststate->haskeytype)
 	{
-		dep = (GISTENTRY *) ((giststate->decompressFn) (e));
+		dep = (GISTENTRY *) ((*fmgr_faddr(&giststate->decompressFn)) (e));
 		gistentryinit(*e, dep->pred, dep->rel, dep->page, dep->offset, dep->bytes,
 					  dep->leafkey);
 		if (dep != e)
@@ -1280,7 +1271,7 @@ gistcentryinit(GISTSTATE *giststate, GISTENTRY *e, char *pr, Relation r,
 	gistentryinit(*e, pr, r, pg, o, b, l);
 	if (giststate->haskeytype)
 	{
-		cep = (GISTENTRY *) ((giststate->compressFn) (e));
+		cep = (GISTENTRY *) ((*fmgr_faddr(&giststate->compressFn)) (e));
 		gistentryinit(*e, cep->pred, cep->rel, cep->page, cep->offset, cep->bytes,
 					  cep->leafkey);
 		if (cep != e)
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index 3e09374584460b590be5845851432b9067950767..de250987755eeb695cba6c94bb091e8c6fcb736b 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -283,13 +283,13 @@ gistindex_keytest(IndexTuple tuple,
 
 		if (key[0].sk_flags & SK_COMMUTE)
 		{
-			test = (*(key[0].sk_func))
+			test = (*fmgr_faddr(&key[0].sk_func))
 				(DatumGetPointer(key[0].sk_argument),
 				 &de, key[0].sk_procedure) ? 1 : 0;
 		}
 		else
 		{
-			test = (*(key[0].sk_func))
+			test = (*fmgr_faddr(&key[0].sk_func))
 				(&de,
 				 DatumGetPointer(key[0].sk_argument),
 				 key[0].sk_procedure) ? 1 : 0;
diff --git a/src/backend/access/index/istrat.c b/src/backend/access/index/istrat.c
index 3fc972a09a1893b1fd8c84ae4f7dca4efb617707..01825cc6848dfa0572df650a7bf8d535c56b0166 100644
--- a/src/backend/access/index/istrat.c
+++ b/src/backend/access/index/istrat.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.15 1998/01/07 21:01:45 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.16 1998/01/15 19:42:02 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -242,22 +242,22 @@ StrategyTermEvaluate(StrategyTerm term,
 		switch (operator->flags ^ entry->sk_flags)
 		{
 			case 0x0:
-				tmpres = (long) FMGR_PTR2(entry->sk_func, entry->sk_procedure,
+				tmpres = (long) FMGR_PTR2(&entry->sk_func, 
 										  left, right);
 				break;
 
 			case SK_NEGATE:
-				tmpres = (long) !FMGR_PTR2(entry->sk_func, entry->sk_procedure,
+				tmpres = (long) !FMGR_PTR2(&entry->sk_func, 
 										   left, right);
 				break;
 
 			case SK_COMMUTE:
-				tmpres = (long) FMGR_PTR2(entry->sk_func, entry->sk_procedure,
+				tmpres = (long) FMGR_PTR2(&entry->sk_func, 
 										  right, left);
 				break;
 
 			case SK_NEGATE | SK_COMMUTE:
-				tmpres = (long) !FMGR_PTR2(entry->sk_func, entry->sk_procedure,
+				tmpres = (long) !FMGR_PTR2(&entry->sk_func,
 										   right, left);
 				break;
 
@@ -521,7 +521,8 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation,
 	entry->sk_flags = 0;
 	entry->sk_procedure =
 		((OperatorTupleForm) GETSTRUCT(tuple))->oprcode;
-	fmgr_info(entry->sk_procedure, &entry->sk_func, &entry->sk_nargs);
+	fmgr_info(entry->sk_procedure, &entry->sk_func);
+	entry->sk_nargs = entry->sk_func.fn_nargs;
 
 	if (!RegProcedureIsValid(entry->sk_procedure))
 	{
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index c903c6fd34a708094973e76d565b66caedfe21c2..b00dae99a0c68b2ed244354f9755e4dd32b00775 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.24 1998/01/07 21:01:52 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.25 1998/01/15 19:42:10 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1487,8 +1487,7 @@ _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum,
 		if (entry->sk_flags & SK_ISNULL || null)
 			return (false);
 
-		result = (long) FMGR_PTR2(entry->sk_func, entry->sk_procedure,
-								  entry->sk_argument, datum);
+		result = (long) FMGR_PTR2(&entry->sk_func, entry->sk_argument, datum);
 		if (result != 0)
 			return (false);
 	}
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index f763af2ee76a9bf87cb40fe3f3b3ccb01d7119ef..32bd77d857064f87bdb843c27ca34d6dd76dd6a2 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.29 1998/01/07 21:01:56 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.30 1998/01/15 19:42:13 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -677,8 +677,7 @@ _bt_compare(Relation rel,
 		}
 		else
 		{
-			tmpres = (long) FMGR_PTR2(entry->sk_func, entry->sk_procedure,
-									  entry->sk_argument, datum);
+			tmpres = (long) FMGR_PTR2(&entry->sk_func, entry->sk_argument, datum);
 		}
 		result = tmpres;
 
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index ce6b3449de22f1d312030b17136de8e0cbcd0b52..b7adfe2179eefd198873a47a4557466b2169fe8f 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.17 1998/01/07 21:02:01 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.18 1998/01/15 19:42:15 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -263,8 +263,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
 		{
 			/* yup, use the appropriate value */
 			test =
-				(long) FMGR_PTR2(cur->sk_func, cur->sk_procedure,
-								 cur->sk_argument, xform[j].sk_argument);
+				(long) FMGR_PTR2(&cur->sk_func, cur->sk_argument, xform[j].sk_argument);
 			if (test)
 				xform[j].sk_argument = cur->sk_argument;
 			else if (j == (BTEqualStrategyNumber - 1))
@@ -381,13 +380,13 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, Size *keysok)
 
 		if (key[0].sk_flags & SK_COMMUTE)
 		{
-			test = (int) (*(key[0].sk_func))
+			test = (int) (*fmgr_faddr(&key[0].sk_func))
 				(DatumGetPointer(key[0].sk_argument),
 				 datum);
 		}
 		else
 		{
-			test = (int) (*(key[0].sk_func))
+			test = (int) (*fmgr_faddr(&key[0].sk_func))
 				(datum,
 				 DatumGetPointer(key[0].sk_argument));
 		}
diff --git a/src/backend/access/rtree/rtree.c b/src/backend/access/rtree/rtree.c
index ac39b4d99b6758ff1e185e9ef04d0bc34004a294..af401accd68edf932cc7ebcd7609d728cebbe18c 100644
--- a/src/backend/access/rtree/rtree.c
+++ b/src/backend/access/rtree/rtree.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.21 1998/01/07 21:02:07 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.22 1998/01/15 19:42:19 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,9 +44,9 @@ typedef struct SPLITVEC
 
 typedef struct RTSTATE
 {
-	func_ptr	unionFn;		/* union function */
-	func_ptr	sizeFn;			/* size function */
-	func_ptr	interFn;		/* intersection function */
+	FmgrInfo	unionFn;		/* union function */
+	FmgrInfo	sizeFn;			/* size function */
+	FmgrInfo	interFn;		/* intersection function */
 } RTSTATE;
 
 /* non-export function prototypes */
@@ -430,10 +430,10 @@ rttighten(Relation r,
 	oldud = (char *) PageGetItem(p, PageGetItemId(p, stk->rts_child));
 	oldud += sizeof(IndexTupleData);
 
-	(*rtstate->sizeFn) (oldud, &old_size);
-	datum = (char *) (*rtstate->unionFn) (oldud, datum);
+	(*fmgr_faddr(&rtstate->sizeFn)) (oldud, &old_size);
+	datum = (char *) (*fmgr_faddr(&rtstate->unionFn)) (oldud, datum);
 
-	(*rtstate->sizeFn) (datum, &newd_size);
+	(*fmgr_faddr(&rtstate->sizeFn)) (datum, &newd_size);
 
 	if (newd_size != old_size)
 	{
@@ -462,7 +462,7 @@ rttighten(Relation r,
 		 * union proc, which is guaranteed to return a rectangle.
 		 */
 
-		tdatum = (char *) (*rtstate->unionFn) (datum, datum);
+		tdatum = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum, datum);
 		rttighten(r, stk->rts_parent, tdatum, att_size, rtstate);
 		pfree(tdatum);
 	}
@@ -686,7 +686,7 @@ rtintinsert(Relation r,
 		WriteBuffer(b);
 		ldatum = (((char *) ltup) + sizeof(IndexTupleData));
 		rdatum = (((char *) rtup) + sizeof(IndexTupleData));
-		newdatum = (char *) (*rtstate->unionFn) (ldatum, rdatum);
+		newdatum = (char *) (*fmgr_faddr(&rtstate->unionFn)) (ldatum, rdatum);
 
 		rttighten(r, stk->rts_parent, newdatum,
 			   (IndexTupleSize(rtup) - sizeof(IndexTupleData)), rtstate);
@@ -765,10 +765,10 @@ picksplit(Relation r,
 			datum_beta = ((char *) item_2) + sizeof(IndexTupleData);
 
 			/* compute the wasted space by unioning these guys */
-			union_d = (char *) (rtstate->unionFn) (datum_alpha, datum_beta);
-			(rtstate->sizeFn) (union_d, &size_union);
-			inter_d = (char *) (rtstate->interFn) (datum_alpha, datum_beta);
-			(rtstate->sizeFn) (inter_d, &size_inter);
+			union_d = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum_alpha, datum_beta);
+			(*fmgr_faddr(&rtstate->sizeFn)) (union_d, &size_union);
+			inter_d = (char *) (*fmgr_faddr(&rtstate->interFn)) (datum_alpha, datum_beta);
+			(*fmgr_faddr(&rtstate->sizeFn)) (inter_d, &size_inter);
 			size_waste = size_union - size_inter;
 
 			pfree(union_d);
@@ -798,12 +798,12 @@ picksplit(Relation r,
 
 	item_1 = (IndexTuple) PageGetItem(page, PageGetItemId(page, seed_1));
 	datum_alpha = ((char *) item_1) + sizeof(IndexTupleData);
-	datum_l = (char *) (*rtstate->unionFn) (datum_alpha, datum_alpha);
-	(*rtstate->sizeFn) (datum_l, &size_l);
+	datum_l = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum_alpha, datum_alpha);
+	(*fmgr_faddr(&rtstate->sizeFn)) (datum_l, &size_l);
 	item_2 = (IndexTuple) PageGetItem(page, PageGetItemId(page, seed_2));
 	datum_beta = ((char *) item_2) + sizeof(IndexTupleData);
-	datum_r = (char *) (*rtstate->unionFn) (datum_beta, datum_beta);
-	(*rtstate->sizeFn) (datum_r, &size_r);
+	datum_r = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum_beta, datum_beta);
+	(*fmgr_faddr(&rtstate->sizeFn)) (datum_r, &size_r);
 
 	/*
 	 * Now split up the regions between the two seeds.	An important
@@ -851,10 +851,10 @@ picksplit(Relation r,
 		}
 
 		datum_alpha = ((char *) item_1) + sizeof(IndexTupleData);
-		union_dl = (char *) (*rtstate->unionFn) (datum_l, datum_alpha);
-		union_dr = (char *) (*rtstate->unionFn) (datum_r, datum_alpha);
-		(*rtstate->sizeFn) (union_dl, &size_alpha);
-		(*rtstate->sizeFn) (union_dr, &size_beta);
+		union_dl = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum_l, datum_alpha);
+		union_dr = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum_r, datum_alpha);
+		(*fmgr_faddr(&rtstate->sizeFn)) (union_dl, &size_alpha);
+		(*fmgr_faddr(&rtstate->sizeFn)) (union_dr, &size_beta);
 
 		/* pick which page to add it to */
 		if (size_alpha - size_l < size_beta - size_r)
@@ -921,9 +921,9 @@ choose(Relation r, Page p, IndexTuple it, RTSTATE *rtstate)
 	{
 		datum = (char *) PageGetItem(p, PageGetItemId(p, i));
 		datum += sizeof(IndexTupleData);
-		(*rtstate->sizeFn) (datum, &dsize);
-		ud = (char *) (*rtstate->unionFn) (datum, id);
-		(*rtstate->sizeFn) (ud, &usize);
+		(*fmgr_faddr(&rtstate->sizeFn)) (datum, &dsize);
+		ud = (char *) (*fmgr_faddr(&rtstate->unionFn)) (datum, id);
+		(*fmgr_faddr(&rtstate->sizeFn)) (ud, &usize);
 		pfree(ud);
 		if (which_grow < 0 || usize - dsize < which_grow)
 		{
@@ -991,18 +991,13 @@ initRtstate(RTSTATE *rtstate, Relation index)
 	RegProcedure union_proc,
 				size_proc,
 				inter_proc;
-	func_ptr	user_fn;
-	int			pronargs;
 
 	union_proc = index_getprocid(index, 1, RT_UNION_PROC);
 	size_proc = index_getprocid(index, 1, RT_SIZE_PROC);
 	inter_proc = index_getprocid(index, 1, RT_INTER_PROC);
-	fmgr_info(union_proc, &user_fn, &pronargs);
-	rtstate->unionFn = user_fn;
-	fmgr_info(size_proc, &user_fn, &pronargs);
-	rtstate->sizeFn = user_fn;
-	fmgr_info(inter_proc, &user_fn, &pronargs);
-	rtstate->interFn = user_fn;
+	fmgr_info(union_proc, &rtstate->unionFn);
+	fmgr_info(size_proc, &rtstate->sizeFn);
+	fmgr_info(inter_proc, &rtstate->interFn);
 	return;
 }
 
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index e7545632864c4e99f692a3e87374aecb9b6f70de..b61bc044905ea30e401878c91f2058dec92d6e43 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.2 1998/01/06 18:52:03 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.3 1998/01/15 19:42:26 pgsql Exp $
  *
  * NOTES
  *	  See acl.h.
@@ -122,7 +122,8 @@ ChangeAcl(char *relname,
 	if (!RelationIsValid(relation))
 		elog(ERROR, "ChangeAcl: could not open '%s'??",
 			 RelationRelationName);
-	fmgr_info(NameEqualRegProcedure, &relkey[0].sk_func, &relkey[0].sk_nargs);
+	fmgr_info(NameEqualRegProcedure, &relkey[0].sk_func);
+	relkey[0].sk_nargs = relkey[0].sk_func.fn_nargs;
 	relkey[0].sk_argument = NameGetDatum(relname);
 	hsdp = heap_beginscan(relation,
 						  0,
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 7336a5ac3eeddbc25a61b0d44ef71895596267e4..c98c877d7d25c76f8460351a4ba056394f7b7ae6 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.34 1998/01/13 04:03:45 scrappy Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.35 1998/01/15 19:42:27 pgsql Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1373,8 +1373,8 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
 	char		nulls[Natts_pg_class];
 	char		replace[Natts_pg_class];
 
-	fmgr_info(ObjectIdEqualRegProcedure, (func_ptr *) &key[0].sk_func,
-			  &key[0].sk_nargs);
+	fmgr_info(ObjectIdEqualRegProcedure, &key[0].sk_func);
+	key[0].sk_nargs = key[0].sk_func.fn_nargs;
 
 	/* ----------------
 	 * This routine handles updates for both the heap and index relation
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 87019690b83cbd19c0f83f5077e0639fe5cc4787..fc62c45a4fbead78a4a3a4a77ed7274aae56112e 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.19 1998/01/06 19:42:31 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.20 1998/01/15 19:42:30 pgsql Exp $
  *
  * NOTES
  *	  these routines moved here from commands/define.c and somewhat cleaned up.
@@ -97,12 +97,12 @@ OperatorGetWithOpenRelation(Relation pg_operator_desc,
 		{0, Anum_pg_operator_oprright, ObjectIdEqualRegProcedure},
 	};
 
-	fmgr_info(NameEqualRegProcedure,
-			  &opKey[0].sk_func, &opKey[0].sk_nargs);
-	fmgr_info(ObjectIdEqualRegProcedure,
-			  &opKey[1].sk_func, &opKey[1].sk_nargs);
-	fmgr_info(ObjectIdEqualRegProcedure,
-			  &opKey[2].sk_func, &opKey[2].sk_nargs);
+	fmgr_info(NameEqualRegProcedure, &opKey[0].sk_func);
+	fmgr_info(ObjectIdEqualRegProcedure, &opKey[1].sk_func);
+	fmgr_info(ObjectIdEqualRegProcedure, &opKey[2].sk_func);
+	opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
+	opKey[1].sk_nargs = opKey[1].sk_func.fn_nargs;
+	opKey[2].sk_nargs = opKey[2].sk_func.fn_nargs;
 
 	/* ----------------
 	 *	form scan key
@@ -482,12 +482,12 @@ OperatorDef(char *operatorName,
 		{0, Anum_pg_operator_oprright, ObjectIdEqualRegProcedure},
 	};
 
-	fmgr_info(NameEqualRegProcedure,
-			  &opKey[0].sk_func, &opKey[0].sk_nargs);
-	fmgr_info(ObjectIdEqualRegProcedure,
-			  &opKey[1].sk_func, &opKey[1].sk_nargs);
-	fmgr_info(ObjectIdEqualRegProcedure,
-			  &opKey[2].sk_func, &opKey[2].sk_nargs);
+	fmgr_info(NameEqualRegProcedure, &opKey[0].sk_func);
+	fmgr_info(ObjectIdEqualRegProcedure, &opKey[1].sk_func);
+	fmgr_info(ObjectIdEqualRegProcedure, &opKey[2].sk_func);
+	opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
+	opKey[1].sk_nargs = opKey[1].sk_func.fn_nargs;
+	opKey[2].sk_nargs = opKey[2].sk_func.fn_nargs;
 
 	operatorObjectId = OperatorGet(operatorName,
 								   leftTypeName,
@@ -781,8 +781,8 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
 		{0, ObjectIdAttributeNumber, ObjectIdEqualRegProcedure},
 	};
 
-	fmgr_info(ObjectIdEqualRegProcedure,
-			  &opKey[0].sk_func, &opKey[0].sk_nargs);
+	fmgr_info(ObjectIdEqualRegProcedure, &opKey[0].sk_func);
+        opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
 
 	for (i = 0; i < Natts_pg_operator; ++i)
 	{
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 63abfcd7ca5d0bbee16e50aad5d83e7ee8aed04b..1168f69b33e916731f0f485c2171c4f0e6baa44a 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.17 1998/01/06 19:42:33 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.18 1998/01/15 19:42:30 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,8 +62,8 @@ TypeGetWithOpenRelation(Relation pg_type_desc,
 	 *	initialize the scan key and begin a scan of pg_type
 	 * ----------------
 	 */
-	fmgr_info(NameEqualRegProcedure,
-			  &typeKey[0].sk_func, &typeKey[0].sk_nargs);
+	fmgr_info(NameEqualRegProcedure, &typeKey[0].sk_func);
+	typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;
 	typeKey[0].sk_argument = PointerGetDatum(typeName);
 
 	scan = heap_beginscan(pg_type_desc,
@@ -324,8 +324,8 @@ TypeCreate(char *typeName,
 		{0, Anum_pg_type_typname, NameEqualRegProcedure}
 	};
 
-	fmgr_info(NameEqualRegProcedure,
-			  &typeKey[0].sk_func, &typeKey[0].sk_nargs);
+	fmgr_info(NameEqualRegProcedure, &typeKey[0].sk_func);
+	typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;
 
 	/* ----------------
 	 *	check that the type is not already defined.
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index ead927c34a6dfd90e37c7b1aa7da33ecb3be9a64..9b5fbda69e8bc18685189f110af75110eb45f7b0 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.37 1998/01/05 16:38:46 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.38 1998/01/15 19:42:36 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -202,8 +202,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 	int32		attr_count,
 				i;
 	AttributeTupleForm *attr;
-	func_ptr   *out_functions;
-	int			dummy;
+	FmgrInfo   *out_functions;
 	Oid			out_func_oid;
 	Oid		   *elements;
 	Datum		value;
@@ -229,12 +228,12 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 
 	if (!binary)
 	{
-		out_functions = (func_ptr *) palloc(attr_count * sizeof(func_ptr));
+		out_functions = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo));
 		elements = (Oid *) palloc(attr_count * sizeof(Oid));
 		for (i = 0; i < attr_count; i++)
 		{
 			out_func_oid = (Oid) GetOutputFunction(attr[i]->atttypid);
-			fmgr_info(out_func_oid, &out_functions[i], &dummy);
+			fmgr_info(out_func_oid, &out_functions[i]);
 			elements[i] = GetTypeElement(attr[i]->atttypid);
 		}
 		nulls = NULL;			/* meaningless, but compiler doesn't know
@@ -272,7 +271,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 			{
 				if (!isnull)
 				{
-					string = (char *) (out_functions[i]) (value, elements[i]);
+					string = (char *) (*fmgr_faddr(&out_functions[i])) (value, elements[i]);
 					CopyAttributeOut(fp, string, delim);
 					pfree(string);
 				}
@@ -357,9 +356,8 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 	HeapTuple	tuple;
 	AttrNumber	attr_count;
 	AttributeTupleForm *attr;
-	func_ptr   *in_functions;
-	int			i,
-				dummy;
+	FmgrInfo   *in_functions;
+	int			i;
 	Oid			in_func_oid;
 	Datum	   *values;
 	char	   *nulls,
@@ -498,12 +496,12 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 
 	if (!binary)
 	{
-		in_functions = (func_ptr *) palloc(attr_count * sizeof(func_ptr));
+		in_functions = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo));
 		elements = (Oid *) palloc(attr_count * sizeof(Oid));
 		for (i = 0; i < attr_count; i++)
 		{
 			in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
-			fmgr_info(in_func_oid, &in_functions[i], &dummy);
+			fmgr_info(in_func_oid, &in_functions[i]);
 			elements[i] = GetTypeElement(attr[i]->atttypid);
 		}
 	}
@@ -574,7 +572,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 				else
 				{
 					values[i] =
-						(Datum) (in_functions[i]) (string,
+						(Datum) (*fmgr_faddr(&in_functions[i])) (string,
 												   elements[i],
 												   attr[i]->attlen);
 
diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c
index 3e9dfc02867c0932451a8cf5cadf97115406da71..cb9a6ea2e46a5b03548cd1dbba48fac4b4444f3b 100644
--- a/src/backend/commands/remove.c
+++ b/src/backend/commands/remove.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.20 1998/01/05 16:38:58 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.21 1998/01/15 19:42:38 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -277,8 +277,8 @@ RemoveType(char *typeName)		/* type name to be removed */
 #endif
 
 	relation = heap_openr(TypeRelationName);
-	fmgr_info(typeKey[0].sk_procedure, &typeKey[0].sk_func,
-			  &typeKey[0].sk_nargs);
+	fmgr_info(typeKey[0].sk_procedure, &typeKey[0].sk_func);
+	typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;
 
 	/* Delete the primary type */
 
@@ -387,7 +387,8 @@ RemoveFunction(char *functionName,		/* function name to be removed */
 
 	key[0].sk_argument = PointerGetDatum(functionName);
 
-	fmgr_info(key[0].sk_procedure, &key[0].sk_func, &key[0].sk_nargs);
+	fmgr_info(key[0].sk_procedure, &key[0].sk_func);
+	key[0].sk_nargs = key[0].sk_func.fn_nargs;
 
 	relation = heap_openr(ProcedureRelationName);
 	scan = heap_beginscan(relation, 0, false, 1, key);
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index f7dca4bcf4157451c668b8a69cc4a7a15f41365a..33062b911bbe4836bb3bbb8e36d5bb0ef9fc89e6 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -43,7 +43,6 @@ static HeapTuple
 GetTupleForTrigger(Relation relation, ItemPointer tid,
 				   bool before);
 
-extern void fmgr_info(Oid procedureId, func_ptr * function, int *nargs);
 extern GlobalMemory CacheCxt;
 
 void
@@ -413,8 +412,7 @@ RelationBuildTriggers(Relation relation)
 
 		build->tgname = nameout(&(pg_trigger->tgname));
 		build->tgfoid = pg_trigger->tgfoid;
-		build->tgfunc = NULL;
-		build->tgplfunc = NULL;
+		build->tgfunc.fn_addr = NULL;
 		build->tgtype = pg_trigger->tgtype;
 		build->tgnargs = pg_trigger->tgnargs;
 		memcpy(build->tgattr, &(pg_trigger->tgattr), 8 * sizeof(int16));
@@ -598,48 +596,17 @@ static HeapTuple
 ExecCallTriggerFunc(Trigger * trigger)
 {
 
-	if (trigger->tgfunc != NULL)
+	if (trigger->tgfunc.fn_addr == NULL)
 	{
-		return (HeapTuple) ((*(trigger->tgfunc)) ());
+		fmgr_info(trigger->tgfoid, &trigger->tgfunc);
 	}
 
-	if (trigger->tgplfunc == NULL)
-	{
-		HeapTuple	procTuple;
-		HeapTuple	langTuple;
-		Form_pg_proc procStruct;
-		Form_pg_language langStruct;
-		int			nargs;
-
-		procTuple = SearchSysCacheTuple(PROOID,
-										ObjectIdGetDatum(trigger->tgfoid),
-										0, 0, 0);
-		if (!HeapTupleIsValid(procTuple))
-		{
-			elog(ERROR, "ExecCallTriggerFunc(): Cache lookup for proc %ld failed",
-				 ObjectIdGetDatum(trigger->tgfoid));
-		}
-		procStruct = (Form_pg_proc) GETSTRUCT(procTuple);
-
-		langTuple = SearchSysCacheTuple(LANOID,
-								   ObjectIdGetDatum(procStruct->prolang),
-										0, 0, 0);
-		if (!HeapTupleIsValid(langTuple))
-		{
-			elog(ERROR, "ExecCallTriggerFunc(): Cache lookup for language %ld failed",
-				 ObjectIdGetDatum(procStruct->prolang));
-		}
-		langStruct = (Form_pg_language) GETSTRUCT(langTuple);
-
-		if (langStruct->lanispl == false)
-		{
-			fmgr_info(trigger->tgfoid, &(trigger->tgfunc), &nargs);
-			return (HeapTuple) ((*(trigger->tgfunc)) ());
-		}
-		fmgr_info(langStruct->lanplcallfoid, &(trigger->tgplfunc), &nargs);
+	if (trigger->tgfunc.fn_plhandler != NULL) {
+		return (HeapTuple) (*(trigger->tgfunc.fn_plhandler))
+							(&trigger->tgfunc);
 	}
 
-	return (HeapTuple) ((*(trigger->tgplfunc)) (trigger->tgfoid));
+	return (HeapTuple) ((*fmgr_faddr(&trigger->tgfunc)) ());
 }
 
 HeapTuple
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 90d57af2f054a0cc9562b91734fb8c26a4debc9b..0d19eb51999f2b72834407951f4607bf202a269d 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.57 1998/01/05 16:39:05 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.58 1998/01/15 19:42:40 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -67,9 +67,9 @@ static int	MESSAGE_LEVEL;		/* message level */
 #define swapLong(a,b)	{long tmp; tmp=a; a=b; b=tmp;}
 #define swapInt(a,b)	{int tmp; tmp=a; a=b; b=tmp;}
 #define swapDatum(a,b)	{Datum tmp; tmp=a; a=b; b=tmp;}
-#define VacAttrStatsEqValid(stats) ( stats->f_cmpeq != NULL )
-#define VacAttrStatsLtGtValid(stats) ( stats->f_cmplt != NULL && \
-								   stats->f_cmpgt != NULL && \
+#define VacAttrStatsEqValid(stats) ( stats->f_cmpeq.fn_addr != NULL )
+#define VacAttrStatsLtGtValid(stats) ( stats->f_cmplt.fn_addr != NULL && \
+								   stats->f_cmpgt.fn_addr != NULL && \
 								   RegProcedureIsValid(stats->outfunc) )
 
 
@@ -484,35 +484,29 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
 			func_operator = oper("=", stats->attr->atttypid, stats->attr->atttypid, true);
 			if (func_operator != NULL)
 			{
-				int			nargs;
-
 				pgopform = (OperatorTupleForm) GETSTRUCT(func_operator);
-				fmgr_info(pgopform->oprcode, &(stats->f_cmpeq), &nargs);
+				fmgr_info(pgopform->oprcode, &(stats->f_cmpeq));
 			}
 			else
-				stats->f_cmpeq = NULL;
+				stats->f_cmpeq.fn_addr = NULL;
 
 			func_operator = oper("<", stats->attr->atttypid, stats->attr->atttypid, true);
 			if (func_operator != NULL)
 			{
-				int			nargs;
-
 				pgopform = (OperatorTupleForm) GETSTRUCT(func_operator);
-				fmgr_info(pgopform->oprcode, &(stats->f_cmplt), &nargs);
+				fmgr_info(pgopform->oprcode, &(stats->f_cmplt));
 			}
 			else
-				stats->f_cmplt = NULL;
+				stats->f_cmplt.fn_addr = NULL;
 
 			func_operator = oper(">", stats->attr->atttypid, stats->attr->atttypid, true);
 			if (func_operator != NULL)
 			{
-				int			nargs;
-
 				pgopform = (OperatorTupleForm) GETSTRUCT(func_operator);
-				fmgr_info(pgopform->oprcode, &(stats->f_cmpgt), &nargs);
+				fmgr_info(pgopform->oprcode, &(stats->f_cmpgt));
 			}
 			else
-				stats->f_cmpgt = NULL;
+				stats->f_cmpgt.fn_addr = NULL;
 
 			pgttup = SearchSysCacheTuple(TYPOID,
 								 ObjectIdGetDatum(stats->attr->atttypid),
@@ -1671,29 +1665,29 @@ vc_attrstats(Relation onerel, VRelStats *vacrelstats, HeapTuple htup)
 			}
 			if (VacAttrStatsLtGtValid(stats))
 			{
-				if ((*(stats->f_cmplt)) (value, stats->min))
+				if ((*fmgr_faddr(&stats->f_cmplt)) (value, stats->min))
 				{
 					vc_bucketcpy(stats->attr, value, &stats->min, &stats->min_len);
 					stats->min_cnt = 0;
 				}
-				if ((*(stats->f_cmpgt)) (value, stats->max))
+				if ((*fmgr_faddr(&stats->f_cmpgt)) (value, stats->max))
 				{
 					vc_bucketcpy(stats->attr, value, &stats->max, &stats->max_len);
 					stats->max_cnt = 0;
 				}
-				if ((*(stats->f_cmpeq)) (value, stats->min))
+				if ((*fmgr_faddr(&stats->f_cmpeq)) (value, stats->min))
 					stats->min_cnt++;
-				else if ((*(stats->f_cmpeq)) (value, stats->max))
+				else if ((*fmgr_faddr(&stats->f_cmpeq)) (value, stats->max))
 					stats->max_cnt++;
 			}
-			if ((*(stats->f_cmpeq)) (value, stats->best))
+			if ((*fmgr_faddr(&stats->f_cmpeq)) (value, stats->best))
 				stats->best_cnt++;
-			else if ((*(stats->f_cmpeq)) (value, stats->guess1))
+			else if ((*fmgr_faddr(&stats->f_cmpeq)) (value, stats->guess1))
 			{
 				stats->guess1_cnt++;
 				stats->guess1_hits++;
 			}
-			else if ((*(stats->f_cmpeq)) (value, stats->guess2))
+			else if ((*fmgr_faddr(&stats->f_cmpeq)) (value, stats->guess2))
 				stats->guess2_hits++;
 			else
 				value_hit = false;
@@ -1880,9 +1874,8 @@ vc_updstats(Oid relid, int npages, int ntups, bool hasindex, VRelStats *vacrelst
 																		 *
 					 pgcform->relname.data) */ )
 				{
-					func_ptr	out_function;
+					FmgrInfo	out_function;
 					char	   *out_string;
-					int			dummy;
 
 					for (i = 0; i < Natts_pg_statistic; ++i)
 						nulls[i] = ' ';
@@ -1895,11 +1888,11 @@ vc_updstats(Oid relid, int npages, int ntups, bool hasindex, VRelStats *vacrelst
 					values[i++] = (Datum) relid;		/* 1 */
 					values[i++] = (Datum) attp->attnum; /* 2 */
 					values[i++] = (Datum) InvalidOid;	/* 3 */
-					fmgr_info(stats->outfunc, &out_function, &dummy);
-					out_string = (*out_function) (stats->min, stats->attr->atttypid);
+					fmgr_info(stats->outfunc, &out_function);
+					out_string = (*fmgr_faddr(&out_function)) (stats->min, stats->attr->atttypid);
 					values[i++] = (Datum) fmgr(TextInRegProcedure, out_string);
 					pfree(out_string);
-					out_string = (char *) (*out_function) (stats->max, stats->attr->atttypid);
+					out_string = (char *) (*fmgr_faddr(&out_function)) (stats->max, stats->attr->atttypid);
 					values[i++] = (Datum) fmgr(TextInRegProcedure, out_string);
 					pfree(out_string);
 
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 2634fb63d990c0cee4cf68a7d303c6a09b663504..a5bb7b893bf5c63b05a51d554cd011e32df98033 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.22 1998/01/07 21:02:47 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.23 1998/01/15 19:44:24 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -826,8 +826,7 @@ ExecMakeFunctionResult(Node *node,
 			if (fcache->nullVect[i] == true)
 				*isNull = true;
 
-		return ((Datum) fmgr_c(fcache->func, fcache->foid, fcache->nargs,
-							   (FmgrValues *) argv, isNull));
+		return ((Datum) fmgr_c(&fcache->func, (FmgrValues *) argv, isNull));
 	}
 }
 
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 62970db8c7bdaa75671cb1515ba329f0ae22c749..feda58bcd672b3b9adf9cd8017cfec76cee92432 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -39,12 +39,9 @@ typedef struct AggFuncInfo
 	Oid			xfn1_oid;
 	Oid			xfn2_oid;
 	Oid			finalfn_oid;
-	func_ptr	xfn1;
-	func_ptr	xfn2;
-	func_ptr	finalfn;
-	int			xfn1_nargs;
-	int			xfn2_nargs;
-	int			finalfn_nargs;
+	FmgrInfo	xfn1;
+	FmgrInfo	xfn2;
+	FmgrInfo	finalfn;
 } AggFuncInfo;
 
 static Datum aggGetAttr(TupleTableSlot *tuple, Aggreg *agg, bool *isNull);
@@ -160,12 +157,6 @@ ExecAgg(Agg *node)
 		Oid			xfn1_oid,
 					xfn2_oid,
 					finalfn_oid;
-		func_ptr	xfn1_ptr,
-					xfn2_ptr,
-					finalfn_ptr;
-		int			xfn1_nargs,
-					xfn2_nargs,
-					finalfn_nargs;
 
 		agg = aggregates[i];
 
@@ -191,18 +182,14 @@ ExecAgg(Agg *node)
 
 		if (OidIsValid(finalfn_oid))
 		{
-			fmgr_info(finalfn_oid, &finalfn_ptr, &finalfn_nargs);
+			fmgr_info(finalfn_oid, &aggFuncInfo[i].finalfn);
 			aggFuncInfo[i].finalfn_oid = finalfn_oid;
-			aggFuncInfo[i].finalfn = finalfn_ptr;
-			aggFuncInfo[i].finalfn_nargs = finalfn_nargs;
 		}
 
 		if (OidIsValid(xfn2_oid))
 		{
-			fmgr_info(xfn2_oid, &xfn2_ptr, &xfn2_nargs);
+			fmgr_info(xfn2_oid, &aggFuncInfo[i].xfn2);
 			aggFuncInfo[i].xfn2_oid = xfn2_oid;
-			aggFuncInfo[i].xfn2 = xfn2_ptr;
-			aggFuncInfo[i].xfn2_nargs = xfn2_nargs;
 			value2[i] = (Datum) AggNameGetInitVal((char *) aggname,
 												  aggp->aggbasetype,
 												  2,
@@ -219,10 +206,8 @@ ExecAgg(Agg *node)
 
 		if (OidIsValid(xfn1_oid))
 		{
-			fmgr_info(xfn1_oid, &xfn1_ptr, &xfn1_nargs);
+			fmgr_info(xfn1_oid, &aggFuncInfo[i].xfn1);
 			aggFuncInfo[i].xfn1_oid = xfn1_oid;
-			aggFuncInfo[i].xfn1 = xfn1_ptr;
-			aggFuncInfo[i].xfn1_nargs = xfn1_nargs;
 			value1[i] = (Datum) AggNameGetInitVal((char *) aggname,
 												  aggp->aggbasetype,
 												  1,
@@ -321,7 +306,7 @@ ExecAgg(Agg *node)
 			if (isNull && !aggregates[i]->usenulls)
 				continue;		/* ignore this tuple for this agg */
 
-			if (aggfns->xfn1)
+			if (aggfns->xfn1.fn_addr != NULL)
 			{
 				if (noInitValue[i])
 				{
@@ -389,20 +374,19 @@ ExecAgg(Agg *node)
 					args[0] = value1[i];
 					args[1] = newVal;
 					value1[i] =
-						(Datum) fmgr_c(aggfns->xfn1, aggfns->xfn1_oid,
-								 aggfns->xfn1_nargs, (FmgrValues *) args,
+						(Datum) fmgr_c(&aggfns->xfn1, 
+								 (FmgrValues *) args,
 									   &isNull1);
 					Assert(!isNull1);
 				}
 			}
 
-			if (aggfns->xfn2)
+			if (aggfns->xfn2.fn_addr != NULL)
 			{
 				Datum		xfn2_val = value2[i];
 
 				value2[i] =
-					(Datum) fmgr_c(aggfns->xfn2, aggfns->xfn2_oid,
-								   aggfns->xfn2_nargs,
+					(Datum) fmgr_c(&aggfns->xfn2,
 								   (FmgrValues *) &xfn2_val, &isNull2);
 				Assert(!isNull2);
 			}
@@ -437,29 +421,27 @@ ExecAgg(Agg *node)
 			 * seems to fix behavior for avg() aggregate. -tgl 12/96
 			 */
 		}
-		else if (aggfns->finalfn && nTuplesAgged > 0)
+		else if (aggfns->finalfn.fn_addr != NULL && nTuplesAgged > 0)
 		{
-			if (aggfns->finalfn_nargs > 1)
+			if (aggfns->finalfn.fn_nargs > 1)
 			{
 				args[0] = (char *) value1[i];
 				args[1] = (char *) value2[i];
 			}
-			else if (aggfns->xfn1)
+			else if (aggfns->xfn1.fn_addr != NULL)
 			{
 				args[0] = (char *) value1[i];
 			}
-			else if (aggfns->xfn2)
+			else if (aggfns->xfn2.fn_addr != NULL)
 			{
 				args[0] = (char *) value2[i];
 			}
 			else
-				elog(ERROR, "ExecAgg: no valid transition functions??");
-			value1[i] =
-				(Datum) fmgr_c(aggfns->finalfn, aggfns->finalfn_oid,
-							   aggfns->finalfn_nargs, (FmgrValues *) args,
-							   &(nulls[i]));
+				elog(WARN, "ExecAgg: no valid transition functions??");
+			value1[i] = (Datum) fmgr_c(&aggfns->finalfn,
+						(FmgrValues *) args, &(nulls[i]));
 		}
-		else if (aggfns->xfn1)
+		else if (aggfns->xfn1.fn_addr != NULL)
 		{
 
 			/*
@@ -467,7 +449,7 @@ ExecAgg(Agg *node)
 			 * fix the else part. -ay 2/95)
 			 */
 		}
-		else if (aggfns->xfn2)
+		else if (aggfns->xfn2.fn_addr != NULL)
 		{
 			value1[i] = value2[i];
 		}
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 47da53703f99a6d122303f5fa63b037bf22bb7b0..5208f94839d64bc7fbac211bbd8db82f6020118c 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.13 1998/01/07 21:04:17 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.14 1998/01/15 19:44:41 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -416,7 +416,8 @@ find_inheritance_children(Oid inhparent)
 	List	   *list = NIL;
 	Oid			inhrelid;
 
-	fmgr_info(F_OIDEQ, &key[0].sk_func, &key[0].sk_nargs);
+	fmgr_info(F_OIDEQ, &key[0].sk_func);
+	key[0].sk_nargs = key[0].sk_func.fn_nargs;
 
 	key[0].sk_argument = ObjectIdGetDatum((Oid) inhparent);
 	relation = heap_openr(InheritsRelationName);
@@ -452,7 +453,8 @@ VersionGetParents(Oid verrelid)
 	Oid			verbaseid;
 	List	   *list = NIL;
 
-	fmgr_info(F_OIDEQ, &key[0].sk_func, &key[0].sk_nargs);
+	fmgr_info(F_OIDEQ, &key[0].sk_func);
+	key[0].sk_nargs = key[0].sk_func.fn_nargs;
 	relation = heap_openr(VersionRelationName);
 	key[0].sk_argument = ObjectIdGetDatum(verrelid);
 	scan = heap_beginscan(relation, 0, false, 1, key);
diff --git a/src/backend/utils/Gen_fmgrtab.sh.in b/src/backend/utils/Gen_fmgrtab.sh.in
index 409372e8ce2f1a41346246bed0b2aa4c2bc632fb..3e04b2d890ff221b219aff5c9f9f955b967a1ecc 100644
--- a/src/backend/utils/Gen_fmgrtab.sh.in
+++ b/src/backend/utils/Gen_fmgrtab.sh.in
@@ -8,7 +8,7 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh.in,v 1.5 1997/10/28 15:02:24 vadim Exp $
+#    $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh.in,v 1.6 1998/01/15 19:44:50 pgsql Exp $
 #
 # NOTES
 #    Passes any -D options on to cpp prior to generating the list
@@ -81,7 +81,7 @@ cat > $HFILE <<FuNkYfMgRsTuFf
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: Gen_fmgrtab.sh.in,v 1.5 1997/10/28 15:02:24 vadim Exp $
+ * $Id: Gen_fmgrtab.sh.in,v 1.6 1998/01/15 19:44:50 pgsql Exp $
  *
  * NOTES
  *	******************************
@@ -111,16 +111,21 @@ typedef struct {
     char *data[MAXFMGRARGS];
 } FmgrValues;
 
+typedef struct {
+    func_ptr	fn_addr;
+    func_ptr	fn_plhandler;
+    Oid		fn_oid;
+    int		fn_nargs;
+} FmgrInfo;
+
 /*
  * defined in fmgr.c
  */
-extern char *fmgr_pl(Oid func_id, int n_arguments, FmgrValues *values,
-	bool *isNull);
-extern char *fmgr_c(func_ptr user_fn, Oid func_id, int n_arguments,
-	FmgrValues *values, bool *isNull);
-extern void fmgr_info(Oid procedureId, func_ptr *function, int *nargs);
+extern char *fmgr_c(FmgrInfo *finfo, FmgrValues *values, bool *isNull);
+extern void fmgr_info(Oid procedureId, FmgrInfo *finfo);
+extern func_ptr fmgr_faddr(FmgrInfo *finfo);
 extern char *fmgr(Oid procedureId, ... );
-extern char *fmgr_ptr(func_ptr user_fn, Oid func_id, ... );
+extern char *fmgr_ptr(FmgrInfo *finfo, ... );
 extern char *fmgr_array_args(Oid procedureId, int nargs, 
 			     char *args[], bool *isNull);
 
@@ -139,11 +144,11 @@ extern void load_file(char *filename);
  *	we must).
  */
 #ifdef TRACE_FMGR_PTR
-#define	FMGR_PTR2(FP, FID, ARG1, ARG2) \
-	fmgr_ptr(FP, FID, 2, ARG1, ARG2)
+#define	FMGR_PTR2(FINFO, ARG1, ARG2) \
+	fmgr_ptr(FINFO, 2, ARG1, ARG2)
 #else
-#define	FMGR_PTR2(FP, FID, ARG1, ARG2) \
-	((FP) ? (*((func_ptr)(FP)))(ARG1, ARG2) : fmgr(FID, ARG1, ARG2))
+#define	FMGR_PTR2(FINFO, ARG1, ARG2) \
+	(((FINFO)->fn_addr) ? (*(fmgr_faddr(FINFO)))(ARG1, ARG2) : fmgr((FINFO)->fn_oid, ARG1, ARG2))
 #endif
 
 /*
@@ -177,7 +182,7 @@ cat > $TABCFILE <<FuNkYfMgRtAbStUfF
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh.in,v 1.5 1997/10/28 15:02:24 vadim Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh.in,v 1.6 1998/01/15 19:44:50 pgsql Exp $
  *
  * NOTES
  *
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 529cddb99e2f22c62b05a003f766b0791f6d6ad5..6d5db4e78327198ed76a239e585a75fa2de2ee37 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.23 1998/01/05 16:39:41 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.24 1998/01/15 19:45:01 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,7 +45,7 @@
 static int	_ArrayCount(char *str, int dim[], int typdelim);
 static char *
 _ReadArrayStr(char *arrayStr, int nitems, int ndim, int dim[],
-			  func_ptr inputproc, Oid typelem, char typdelim,
+			  FmgrInfo *inputproc, Oid typelem, char typdelim,
 			  int typlen, bool typbyval, char typalign,
 			  int *nbytes);
 
@@ -105,10 +105,9 @@ array_in(char *string,			/* input array in external form */
 			   *p,
 			   *q,
 			   *r;
-	func_ptr	inputproc;
+	FmgrInfo	inputproc;
 	int			i,
-				nitems,
-				dummy;
+				nitems;
 	int32		nbytes;
 	char	   *dataPtr;
 	ArrayType  *retval = NULL;
@@ -120,7 +119,7 @@ array_in(char *string,			/* input array in external form */
 	system_cache_lookup(element_type, true, &typlen, &typbyval, &typdelim,
 						&typelem, &typinput, &typalign);
 
-	fmgr_info(typinput, &inputproc, &dummy);
+	fmgr_info(typinput, &inputproc);
 
 	string_save = (char *) palloc(strlen(string) + 3);
 	strcpy(string_save, string);
@@ -208,7 +207,7 @@ array_in(char *string,			/* input array in external form */
 	{
 		/* array not a large object */
 		dataPtr =
-			(char *) _ReadArrayStr(p, nitems, ndim, dim, inputproc, typelem,
+			(char *) _ReadArrayStr(p, nitems, ndim, dim, &inputproc, typelem,
 								   typdelim, typlen, typbyval, typalign,
 								   &nbytes);
 		nbytes += ARR_OVERHEAD(ndim);
@@ -367,7 +366,7 @@ _ReadArrayStr(char *arrayStr,
 			  int nitems,
 			  int ndim,
 			  int dim[],
-			  func_ptr inputproc,		/* function used for the
+			  FmgrInfo *inputproc,		/* function used for the
 										 * conversion */
 			  Oid typelem,
 			  char typdelim,
@@ -461,7 +460,7 @@ _ReadArrayStr(char *arrayStr,
 		*q = '\0';
 		if (i >= nitems)
 			elog(ERROR, "array_in: illformed array constant");
-		values[i] = (*inputproc) (p, typelem);
+		values[i] = (*fmgr_faddr(inputproc)) (p, typelem);
 		p = ++q;
 		if (!eoArray)
 
@@ -620,7 +619,7 @@ array_out(ArrayType *v, Oid element_type)
 	char		typdelim;
 	Oid			typoutput,
 				typelem;
-	func_ptr	outputproc;
+	FmgrInfo	outputproc;
 	char		typalign;
 
 	char	   *p,
@@ -634,7 +633,6 @@ array_out(ArrayType *v, Oid element_type)
 				k,
 				indx[MAXDIM];
 	bool		dummy_bool;
-	int			dummy_int;
 	int			ndim,
 			   *dim;
 
@@ -662,7 +660,7 @@ array_out(ArrayType *v, Oid element_type)
 
 	system_cache_lookup(element_type, false, &typlen, &typbyval,
 						&typdelim, &typelem, &typoutput, &typalign);
-	fmgr_info(typoutput, &outputproc, &dummy_int);
+	fmgr_info(typoutput, &outputproc);
 	sprintf(delim, "%c", typdelim);
 	ndim = ARR_NDIM(v);
 	dim = ARR_DIMS(v);
@@ -688,21 +686,21 @@ array_out(ArrayType *v, Oid element_type)
 			switch (typlen)
 			{
 				case 1:
-					values[i] = (*outputproc) (*p, typelem);
+					values[i] = (*fmgr_faddr(&outputproc)) (*p, typelem);
 					break;
 				case 2:
-					values[i] = (*outputproc) (*(int16 *) p, typelem);
+					values[i] = (*fmgr_faddr(&outputproc)) (*(int16 *) p, typelem);
 					break;
 				case 3:
 				case 4:
-					values[i] = (*outputproc) (*(int32 *) p, typelem);
+					values[i] = (*fmgr_faddr(&outputproc)) (*(int32 *) p, typelem);
 					break;
 			}
 			p += typlen;
 		}
 		else
 		{
-			values[i] = (*outputproc) (p, typelem);
+			values[i] = (*fmgr_faddr(&outputproc)) (p, typelem);
 			if (typlen > 0)
 				p += typlen;
 			else
diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c
index de2306815bd5ecb9aaf5b818e33c6d13c6f2f3da..cfecc121ae3c4821d5f90afae1ddc9d9e4a34586 100644
--- a/src/backend/utils/adt/sets.c
+++ b/src/backend/utils/adt/sets.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.11 1998/01/05 16:40:17 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.12 1998/01/15 19:45:09 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -117,8 +117,8 @@ SetDefine(char *querystr, char *typename)
 		procrel = heap_openr(ProcedureRelationName);
 		RelationSetLockForWrite(procrel);
 		fmgr_info(ObjectIdEqualRegProcedure,
-				  &oidKey[0].sk_func,
-				  &oidKey[0].sk_nargs);
+				  &oidKey[0].sk_func);
+		oidKey[0].sk_nargs = oidKey[0].sk_func.fn_nargs;
 		oidKey[0].sk_argument = ObjectIdGetDatum(setoid);
 		pg_proc_scan = heap_beginscan(procrel,
 									  0,
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 6c3ff360fb763007fd292c869c1ff86e8ba0a0bc..89c3446cfbc14623f46880747988c0177d5bdf27 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.20 1998/01/07 21:06:08 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.21 1998/01/15 19:45:28 pgsql Exp $
  *
  * Notes:
  *		XXX This needs to use exception.h to handle recovery when
@@ -213,8 +213,8 @@ CatalogCacheInitializeCache(struct catcache * cache,
 				EQPROC(tupdesc->attrs[cache->cc_key[i] - 1]->atttypid);
 
 			fmgr_info(cache->cc_skey[i].sk_procedure,
-					  (func_ptr *) &cache->cc_skey[i].sk_func,
-					  (int *) &cache->cc_skey[i].sk_nargs);
+					  &cache->cc_skey[i].sk_func);
+			cache->cc_skey[i].sk_nargs = cache->cc_skey[i].sk_func.fn_nargs;
 
 			CACHE5_elog(DEBUG, "CatalogCacheInit %16s %d %d %x",
 						&relation->rd_rel->relname,
diff --git a/src/backend/utils/cache/fcache.c b/src/backend/utils/cache/fcache.c
index 8eb1e7e89e8910a3b20edce564645da1d48e5c60..485a1d01bae893762838d3724e5cb18cbcf30edf 100644
--- a/src/backend/utils/cache/fcache.c
+++ b/src/backend/utils/cache/fcache.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.9 1998/01/07 21:06:11 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.10 1998/01/15 19:45:29 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -98,6 +98,7 @@ init_fcache(Oid foid,
 	 * ----------------
 	 */
 	retval = (FunctionCachePtr) palloc(sizeof(FunctionCache));
+	memset(retval, 0, sizeof(FunctionCache));
 
 	if (!use_syscache)
 		elog(ERROR, "what the ????, init the fcache without the catalogs?");
@@ -281,10 +282,12 @@ init_fcache(Oid foid,
 
 
 
-	if (retval->language != SQLlanguageId)
-		fmgr_info(foid, &(retval->func), &(retval->nargs));
-	else
-		retval->func = (func_ptr) NULL;
+	if (retval->language != SQLlanguageId) {
+		fmgr_info(foid, &(retval->func));
+		retval->nargs = retval->func.fn_nargs;
+	} else {
+		retval->func.fn_addr = (func_ptr) NULL;
+	}
 
 
 	return (retval);
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 90bd2fbac8f0369e94bd48f9ecb55665d8c6ee51..9e706e4bf3f0debf4c5f8421a3d33e1a3e1de039 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.33 1998/01/14 15:48:32 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.34 1998/01/15 19:45:31 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2014,7 +2014,8 @@ init_irels(void)
 		/* have to reinit the function pointers in the strategy maps */
 		for (i = 0; i < am->amstrategies; i++)
 			fmgr_info(SMD(i).sk_procedure,
-					  &(SMD(i).sk_func), &(SMD(i).sk_nargs));
+					  &(SMD(i).sk_func));
+			SMD(i).sk_nargs = SMD(i).sk_func.fn_nargs;
 
 
 		/*
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 7a3798ebe1131574a3d1a56c7b0eab990a1e4ec8..6a11bda292c295c3c2732eb4ca4038c6cb445f81 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.9 1998/01/07 21:06:28 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.10 1998/01/15 19:45:58 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,78 +32,64 @@
 #include "commands/trigger.h"
 
 
-char	   *
-fmgr_pl(Oid func_id,
-		int n_arguments,
-		FmgrValues * values,
-		bool * isNull)
-{
-	HeapTuple	procedureTuple;
-	HeapTuple	languageTuple;
-	Form_pg_proc procedureStruct;
-	Form_pg_language languageStruct;
-	func_ptr	plcall_fn;
-	int			plcall_nargs;
-
-	/* Fetch the pg_proc tuple from the syscache */
-	procedureTuple = SearchSysCacheTuple(PROOID,
-										 ObjectIdGetDatum(func_id),
-										 0, 0, 0);
-	if (!HeapTupleIsValid(procedureTuple))
-	{
-		elog(ERROR, "fmgr_pl(): Cache lookup of procedure %ld failed.",
-			 ObjectIdGetDatum(func_id));
-	}
-	procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
+static        FmgrInfo        *fmgr_pl_finfo;
 
-	/* Fetch the pg_language tuple from the syscache */
-	languageTuple = SearchSysCacheTuple(LANOID,
-							  ObjectIdGetDatum(procedureStruct->prolang),
-										0, 0, 0);
-	if (!HeapTupleIsValid(languageTuple))
-	{
-		elog(ERROR, "fmgr_pl(): Cache lookup of language %ld for procedure %ld failed.",
-			 ObjectIdGetDatum(procedureStruct->prolang),
-			 ObjectIdGetDatum(func_id));
-	}
-	languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
-
-	/* Get the function pointer for the PL call handler */
-	fmgr_info(languageStruct->lanplcallfoid, &plcall_fn, &plcall_nargs);
-	if (plcall_fn == NULL)
-	{
-		elog(ERROR, "fmgr_pl(): failed to load PL handler for procedure %ld.",
-			 ObjectIdGetDatum(func_id));
+static char      * 
+fmgr_pl(char *arg0, ...)
+{
+	va_list         pvar;
+	FmgrValues      values;
+	bool            isNull = false;
+	int             i;
+
+	memset(&values, 0, sizeof(values));
+
+	if (fmgr_pl_finfo->fn_nargs > 0) {
+		values.data[0] = arg0;
+		if (fmgr_pl_finfo->fn_nargs > 1) {
+			va_start(pvar, arg0);
+			for (i = 1; i < fmgr_pl_finfo->fn_nargs; i++) {
+				values.data[i] = va_arg(pvar, char *);
+			}
+			va_end(pvar);
+		}
 	}
 
 	/* Call the PL handler */
 	CurrentTriggerData = NULL;
-	return (*plcall_fn) (func_id,
-						 n_arguments,
-						 values,
-						 isNull);
-}
-
-
-char	   *
-fmgr_c(func_ptr user_fn,
-	   Oid func_id,
-	   int n_arguments,
-	   FmgrValues * values,
-	   bool * isNull)
-{
-	char	   *returnValue = (char *) NULL;
-
-
+	return (*(fmgr_pl_finfo->fn_plhandler)) (fmgr_pl_finfo,
+						&values,
+						&isNull);
+}     
+
+
+char     *
+fmgr_c(FmgrInfo *finfo,
+	FmgrValues * values,
+	bool * isNull)
+{  
+	char       *returnValue = (char *) NULL;
+	int        n_arguments = finfo->fn_nargs;
+	func_ptr   user_fn = fmgr_faddr(finfo);
+        
+        
 	if (user_fn == (func_ptr) NULL)
 	{
 
 		/*
 		 * a NULL func_ptr denotet untrusted function (in postgres 4.2).
-		 * Untrusted functions have very limited use and is clumsy. We now
-		 * use this feature for procedural languages.
+		 * Untrusted functions have very limited use and is clumsy. We
+		 * just get rid of it.
 		 */
-		return fmgr_pl(func_id, n_arguments, values, isNull);
+		elog(WARN, "internal error: untrusted function not supported.");
+	}
+
+	/*
+	 * If finfo contains a PL handler for this function,
+	 * call that instead.
+	 */
+	if (finfo->fn_plhandler != NULL) {
+	    return (*(finfo->fn_plhandler))(finfo, values, isNull);
 	}
 
 	switch (n_arguments)
@@ -164,14 +150,14 @@ fmgr_c(func_ptr user_fn,
 			break;
 		default:
 			elog(ERROR, "fmgr_c: function %d: too many arguments (%d > %d)",
-				 func_id, n_arguments, MAXFMGRARGS);
+				 finfo->fn_oid, n_arguments, MAXFMGRARGS);
 			break;
 	}
 	return (returnValue);
 }
 
 void
-fmgr_info(Oid procedureId, func_ptr * function, int *nargs)
+fmgr_info(Oid procedureId, FmgrInfo *finfo)
 {
 	func_ptr	user_fn = NULL;
 	FmgrCall   *fcp;
@@ -181,6 +167,10 @@ fmgr_info(Oid procedureId, func_ptr * function, int *nargs)
 	Form_pg_language languageStruct;
 	Oid			language;
 
+	finfo->fn_addr = NULL;
+	finfo->fn_plhandler = NULL;
+	finfo->fn_oid = procedureId;
+
 	if (!(fcp = fmgr_isbuiltin(procedureId)))
 	{
 		procedureTuple = SearchSysCacheTuple(PROOID,
@@ -191,29 +181,29 @@ fmgr_info(Oid procedureId, func_ptr * function, int *nargs)
 			elog(ERROR, "fmgr_info: function %d: cache lookup failed\n",
 				 procedureId);
 		}
-		procedureStruct = (FormData_pg_proc *)
-			GETSTRUCT(procedureTuple);
+		procedureStruct = (FormData_pg_proc *) GETSTRUCT(procedureTuple);
 		if (!procedureStruct->proistrusted)
 		{
-			*function = (func_ptr) NULL;
-			*nargs = procedureStruct->pronargs;
+			finfo->fn_addr = (func_ptr) NULL;
+			finfo->fn_nargs = procedureStruct->pronargs;
 			return;
 		}
 		language = procedureStruct->prolang;
 		switch (language)
 		{
 			case INTERNALlanguageId:
-				user_fn = fmgr_lookupByName(procedureStruct->proname.data);
-				if (!user_fn)
-					elog(ERROR, "fmgr_info: function %s: not in internal table",
-						 procedureStruct->proname.data);
+				finfo->fn_addr = 
+							fmgr_lookupByName(procedureStruct->proname.data);
+				if (!finfo->fn_addr)
+					elog(WARN, "fmgr_info: function %s: not in internal table",
+								procedureStruct->proname.data);
 				break;
 			case ClanguageId:
-				user_fn = fmgr_dynamic(procedureId, nargs);
+				finfo->fn_addr = fmgr_dynamic(procedureId, &(finfo->fn_nargs));
 				break;
 			case SQLlanguageId:
-				user_fn = (func_ptr) NULL;
-				*nargs = procedureStruct->pronargs;
+				finfo->fn_addr = (func_ptr) NULL;
+				finfo->fn_nargs = procedureStruct->pronargs;
 				break;
 			default:
 
@@ -236,8 +226,12 @@ fmgr_info(Oid procedureId, func_ptr * function, int *nargs)
 					GETSTRUCT(languageTuple);
 				if (languageStruct->lanispl)
 				{
-					user_fn = (func_ptr) NULL;
-					*nargs = procedureStruct->pronargs;
+					FmgrInfo	plfinfo;
+
+					fmgr_info(((Form_pg_language)GETSTRUCT(languageTuple))->lanplcallfoid, &plfinfo);
+					finfo->fn_addr = (func_ptr) fmgr_pl;
+					finfo->fn_plhandler = plfinfo.fn_addr;
+					finfo->fn_nargs = procedureStruct->pronargs;
 				}
 				else
 				{
@@ -249,10 +243,16 @@ fmgr_info(Oid procedureId, func_ptr * function, int *nargs)
 	}
 	else
 	{
-		user_fn = fcp->func;
-		*nargs = fcp->nargs;
+		finfo->fn_addr = fcp->func;
+		finfo->fn_nargs = fcp->nargs;
 	}
-	*function = user_fn;
+}
+
+func_ptr
+fmgr_faddr(FmgrInfo *finfo)
+{
+    fmgr_pl_finfo = finfo;
+    return finfo->fn_addr;
 }
 
 /*
@@ -273,12 +273,13 @@ fmgr(Oid procedureId,...)
 	register	i;
 	int			pronargs;
 	FmgrValues	values;
-	func_ptr	user_fn;
+	FmgrInfo	finfo;
 	bool		isNull = false;
 
 	va_start(pvar, procedureId);
 
-	fmgr_info(procedureId, &user_fn, &pronargs);
+	fmgr_info(procedureId, &finfo);
+	pronargs = finfo.fn_nargs;
 
 	if (pronargs > MAXFMGRARGS)
 	{
@@ -290,8 +291,7 @@ fmgr(Oid procedureId,...)
 	va_end(pvar);
 
 	/* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
-	return (fmgr_c(user_fn, procedureId, pronargs, &values,
-				   &isNull));
+	return (fmgr_c(&finfo, &values, &isNull));
 }
 
 /*
@@ -301,20 +301,26 @@ fmgr(Oid procedureId,...)
  * the pointer, but it's available for use with macros in fmgr.h if you
  * want this routine to do sanity-checking for you.
  *
- * func_ptr, func_id, n_arguments, args...
+ * funcinfo, n_arguments, args...
  */
 #ifdef NOT_USED
 char	   *
-fmgr_ptr(func_ptr user_fn, Oid func_id,...)
+fmgr_ptr(FmgrInfo *finfo, ...)
 {
 	va_list		pvar;
 	register	i;
 	int			n_arguments;
+	FmgrInfo	local_finfo;
 	FmgrValues	values;
 	bool		isNull = false;
 
-	va_start(pvar, func_id);
+        local_finfo->fn_addr = finfo->fn_addr;
+	local_finfo->fn_plhandler = finfo->fn_plhandler;
+	local_finfo->fn_oid = finfo->fn_oid;
+
+	va_start(pvar, finfo);
 	n_arguments = va_arg(pvar, int);
+	local_finfo->fn_nargs = n_arguments;
 	if (n_arguments > MAXFMGRARGS)
 	{
 		elog(ERROR, "fmgr_ptr: function %d: too many arguments (%d > %d)",
@@ -325,8 +331,7 @@ fmgr_ptr(func_ptr user_fn, Oid func_id,...)
 	va_end(pvar);
 
 	/* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
-	return (fmgr_c(user_fn, func_id, n_arguments, &values,
-				   &isNull));
+	return (fmgr_c(&local_finfo, &values, &isNull));
 }
 
 #endif
@@ -339,16 +344,14 @@ fmgr_ptr(func_ptr user_fn, Oid func_id,...)
 char	   *
 fmgr_array_args(Oid procedureId, int nargs, char *args[], bool * isNull)
 {
-	func_ptr	user_fn;
-	int			true_arguments;
+	FmgrInfo	finfo;
 
-	fmgr_info(procedureId, &user_fn, &true_arguments);
+	fmgr_info(procedureId, &finfo);
+	finfo.fn_nargs = nargs;
 
 	/* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
 	return
-		(fmgr_c(user_fn,
-				procedureId,
-				true_arguments,
+		(fmgr_c(&finfo,
 				(FmgrValues *) args,
 				isNull));
 }
diff --git a/src/backend/utils/sort/lselect.c b/src/backend/utils/sort/lselect.c
index ad8fc9764fcb6761923a7889093dcc612bde6486..c5ee02e7e9c712d5a233b2909924ff1b66547937 100644
--- a/src/backend/utils/sort/lselect.c
+++ b/src/backend/utils/sort/lselect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.9 1997/09/18 05:37:30 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.10 1998/01/15 19:46:08 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -212,14 +212,14 @@ tuplecmp(HeapTuple ltup, HeapTuple rtup, LeftistContext context)
 		if (context->scanKeys[nkey].sk_flags & SK_COMMUTE)
 		{
 			if (!(result =
-			   (long) (*context->scanKeys[nkey].sk_func) (rattr, lattr)))
+			   (long) (*fmgr_faddr(&context->scanKeys[nkey].sk_func)) (rattr, lattr)))
 				result =
-					-(long) (*context->scanKeys[nkey].sk_func) (lattr, rattr);
+					-(long) (*fmgr_faddr(&context->scanKeys[nkey].sk_func)) (lattr, rattr);
 		}
 		else if (!(result =
-			   (long) (*context->scanKeys[nkey].sk_func) (lattr, rattr)))
+			   (long) (*fmgr_faddr(&context->scanKeys[nkey].sk_func)) (lattr, rattr)))
 			result =
-				-(long) (*context->scanKeys[nkey].sk_func) (rattr, lattr);
+				-(long) (*fmgr_faddr(&context->scanKeys[nkey].sk_func)) (rattr, lattr);
 		nkey++;
 	}
 	return (result == 1);
diff --git a/src/backend/utils/sort/psort.c b/src/backend/utils/sort/psort.c
index 682e2534ff4cf921ad87846ca3128816b3da9243..99eb183adbca988a84f908777e7c683507338b44 100644
--- a/src/backend/utils/sort/psort.c
+++ b/src/backend/utils/sort/psort.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/psort.c,v 1.31 1998/01/13 04:04:57 scrappy Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/psort.c,v 1.32 1998/01/15 19:46:10 pgsql Exp $
  *
  * NOTES
  *		Sorts the first relation into the second relation.
@@ -1115,11 +1115,11 @@ _psort_cmp (HeapTuple *ltup, HeapTuple *rtup)
 		
 		if (PsortKeys[nkey].sk_flags & SK_COMMUTE)
 		{
-	    	if (!(result = -(long) (*PsortKeys[nkey].sk_func) (rattr, lattr)))
-			result = (long) (*PsortKeys[nkey].sk_func) (lattr, rattr);
+	    	if (!(result = -(long) (*fmgr_faddr(&PsortKeys[nkey].sk_func)) (rattr, lattr)))
+			result = (long) (*fmgr_faddr(&PsortKeys[nkey].sk_func)) (lattr, rattr);
 		}
-		else if (!(result = -(long) (*PsortKeys[nkey].sk_func) (lattr, rattr)))
-		    result = (long) (*PsortKeys[nkey].sk_func) (rattr, lattr);
+		else if (!(result = -(long) (*fmgr_faddr(&PsortKeys[nkey].sk_func)) (lattr, rattr)))
+		    result = (long) (*fmgr_faddr(&PsortKeys[nkey].sk_func)) (rattr, lattr);
 		nkey++;
     }
     return (result);
diff --git a/src/include/access/gist.h b/src/include/access/gist.h
index d6519cd132c0f31905e8f80f72f313150453547c..15294ce06ccc8e2f074ffe73773f50b422f05470 100644
--- a/src/include/access/gist.h
+++ b/src/include/access/gist.h
@@ -21,6 +21,8 @@
 #include <utils/rel.h>
 #include <storage/off.h>
 
+#include <fmgr.h>
+
 /*
 ** You can have as many strategies as you please in GiSTs, as
 ** long as your consistent method can handle them
@@ -71,13 +73,13 @@ typedef struct GISTSTACK
 
 typedef struct GISTSTATE
 {
-	func_ptr	consistentFn;
-	func_ptr	unionFn;
-	func_ptr	compressFn;
-	func_ptr	decompressFn;
-	func_ptr	penaltyFn;
-	func_ptr	picksplitFn;
-	func_ptr	equalFn;
+	FmgrInfo	consistentFn;
+	FmgrInfo	unionFn;
+	FmgrInfo	compressFn;
+	FmgrInfo	decompressFn;
+	FmgrInfo	penaltyFn;
+	FmgrInfo	picksplitFn;
+	FmgrInfo	equalFn;
 	bool		haskeytype;
 	bool		keytypbyval;
 } GISTSTATE;
diff --git a/src/include/access/skey.h b/src/include/access/skey.h
index f40efc1e5b4472942aaf5298ec93ff5920a7315c..4cbf18197f28cb1d163eb47d5bdb575685f61032 100644
--- a/src/include/access/skey.h
+++ b/src/include/access/skey.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: skey.h,v 1.6 1997/09/08 21:51:01 momjian Exp $
+ * $Id: skey.h,v 1.7 1998/01/15 19:46:18 pgsql Exp $
  *
  *
  * Note:
@@ -17,13 +17,14 @@
 #define SKEY_H
 
 #include <access/attnum.h>
+#include <fmgr.h>
 
 typedef struct ScanKeyData
 {
 	bits16		sk_flags;		/* flags */
 	AttrNumber	sk_attno;		/* domain number */
 	RegProcedure sk_procedure;	/* procedure OID */
-	func_ptr	sk_func;
+	FmgrInfo	sk_func;
 	int32		sk_nargs;
 	Datum		sk_argument;	/* data to compare */
 } ScanKeyData;
diff --git a/src/include/access/valid.h b/src/include/access/valid.h
index 555ef7446b419eda02e16c24b3da9150c3901f43..9a95d9c33290097b80d9ff7caefacda8ae7566a1 100644
--- a/src/include/access/valid.h
+++ b/src/include/access/valid.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: valid.h,v 1.11 1997/11/24 05:09:41 momjian Exp $
+ * $Id: valid.h,v 1.12 1998/01/15 19:46:18 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -71,13 +71,13 @@ do \
 			break; \
 		} \
  \
-		if (__cur_keys->sk_func == (func_ptr) oideq)	/* optimization */ \
+		if (__cur_keys->sk_func.fn_addr == (func_ptr) oideq)	/* optimization */ \
 			__test = (__cur_keys->sk_argument == __atp); \
 		else if (__cur_keys->sk_flags & SK_COMMUTE) \
-			__test = (long) FMGR_PTR2(__cur_keys->sk_func, __cur_keys->sk_procedure, \
+			__test = (long) FMGR_PTR2(&__cur_keys->sk_func, \
 									__cur_keys->sk_argument, __atp); \
 		else \
-			__test = (long) FMGR_PTR2(__cur_keys->sk_func, __cur_keys->sk_procedure, \
+			__test = (long) FMGR_PTR2(&__cur_keys->sk_func, \
 									__atp, __cur_keys->sk_argument); \
  \
 		if (!__test == !(__cur_keys->sk_flags & SK_NEGATE)) \
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index 2f72f767e5b6e4de953df27a1e9eae1ef29cfd66..250e8952dd01ec8db1854d7612dc6d0f67743a9d 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: vacuum.h,v 1.11 1997/11/26 01:26:08 momjian Exp $
+ * $Id: vacuum.h,v 1.12 1998/01/15 19:46:24 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -78,7 +78,7 @@ typedef struct
 				nonnull_cnt;
 	int32		max_cnt,
 				min_cnt;
-	func_ptr	f_cmpeq,
+	FmgrInfo	f_cmpeq,
 				f_cmplt,
 				f_cmpgt;
 	regproc		outfunc;
diff --git a/src/include/utils/fcache.h b/src/include/utils/fcache.h
index f9ace84b13ac5808e0a1d721e3a2091e837363bd..504ac8e2adbca361b4a531b0ff534da23310032b 100644
--- a/src/include/utils/fcache.h
+++ b/src/include/utils/fcache.h
@@ -6,19 +6,21 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fcache.h,v 1.5 1997/09/08 21:54:57 momjian Exp $
+ * $Id: fcache.h,v 1.6 1998/01/15 19:46:36 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef FCACHE_H
 #define FCACHE_H
 
+#include <fmgr.h>
+
 
 typedef struct
 {
 	int			typlen;			/* length of the return type */
 	int			typbyval;		/* true if return type is pass by value */
-	func_ptr	func;			/* address of function to call (for c
+	FmgrInfo	func;			/* address of function to call (for c
 								 * funcs) */
 	Oid			foid;			/* oid of the function in pg_proc */
 	Oid			language;		/* oid of the language in pg_language */
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 2de7b31671de4fb971d4916f30e2aa29c8ff91e8..cbfa4dfba4669623550020adcf27274f7729ffc6 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rel.h,v 1.14 1997/11/21 19:12:32 momjian Exp $
+ * $Id: rel.h,v 1.15 1998/01/15 19:46:37 pgsql Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,8 +24,7 @@ typedef struct Trigger
 {
 	char	   *tgname;
 	Oid			tgfoid;
-	func_ptr	tgfunc;
-	func_ptr	tgplfunc;
+	FmgrInfo	tgfunc;
 	int16		tgtype;
 	int16		tgnargs;
 	int16		tgattr[8];