/*
 * fmgr.c --
 *	the C function manager interface.
 */

#include <stdio.h>
#include <varargs.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "utils/dynamic_loader.h"
#include "utils/fmgr.h"

#include "nodes/pg_lisp.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_language.h"
#include "catalog/syscache.h"
#include "rules/params.h"

#include "utils/log.h"
RcsId("$Header: /general/TFA/unclassified/src/utils/postgres-v3r1/src/utils/fmgr/RCS/fmgr.c,v 1.75 1991/11/18 16:54:39 clarsen Exp $");

/*
 *	procedure OID -> function mapping
 *
 *	XXX Keep this thing sorted by procedure OID!
 *	    It gets binary-searched ...
 */

typedef struct {
	ObjectId	proid;
	int16		nargs;
	FmgrFunction	func;
} FmgrCall;

static FmgrCall	builtins[] = {
	{ F_BOOLIN,		1, (FmgrFunction) boolin },
	{ F_BOOLOUT,		1, (FmgrFunction) boolout },
	{ F_BYTEAIN,		1, (FmgrFunction) byteain },
	{ F_BYTEAOUT,		1, (FmgrFunction) byteaout },
	{ F_CHARIN,		1, (FmgrFunction) charin },
	{ F_CHAROUT,		1, (FmgrFunction) charout },
	{ F_CHAR16IN,		1, (FmgrFunction) char16in },
	{ F_CHAR16OUT,		1, (FmgrFunction) char16out },
	{ F_DATETIMEIN,		1, (FmgrFunction) dtin },
	{ F_DATETIMEOUT,	1, (FmgrFunction) dtout },
	{ F_INT2IN,		1, (FmgrFunction) int2in },
	{ F_INT2OUT,		1, (FmgrFunction) int2out },
	{ F_INT28IN,		1, (FmgrFunction) int28in },
	{ F_INT28OUT,		1, (FmgrFunction) int28out },
	{ F_INT4IN,		1, (FmgrFunction) int4in },
	/* F_OIDIN == F_INT4IN */
	{ F_INT4OUT,		1, (FmgrFunction) int4out },
	/* F_OIDOUT == F_INT4OUT */
	{ F_REGPROCIN,		1, (FmgrFunction) regprocin },
	{ F_REGPROCOUT,		1, (FmgrFunction) regprocout },
	{ F_TEXTIN,		1, (FmgrFunction) textin },
	{ F_TEXTOUT,		1, (FmgrFunction) textout },
	{ F_TIDIN,		1, (FmgrFunction) tidin },
	{ F_TIDOUT,		1, (FmgrFunction) tidout },
	{ F_XIDIN,		1, (FmgrFunction) StringFormTransactionId },
	{ F_XIDOUT,		1, (FmgrFunction) TransactionIdFormString },
	{ F_CIDIN,		1, (FmgrFunction) cidin },
	{ F_CIDOUT,		1, (FmgrFunction) cidout },
	{ F_OID8IN,		1, (FmgrFunction) oid8in },
	{ F_OID8OUT,		1, (FmgrFunction) oid8out },
	{ F_LOCKIN,		1, (FmgrFunction) StringToRuleLock },
	{ F_LOCKOUT,		1, (FmgrFunction) RuleLockToString },
	{ F_STUBIN,		1, (FmgrFunction) stubin },
	{ F_STUBOUT,		1, (FmgrFunction) stubout },

 	{ F_BOOLEQ,		2, (FmgrFunction) chareq },
	{ F_CHAREQ,		2, (FmgrFunction) chareq },
	{ F_CHAR16EQ,		2, (FmgrFunction) char16eq },
	{ F_INT2EQ,		2, (FmgrFunction) int2eq },
	{ F_INT2LT,		2, (FmgrFunction) int2lt },
	{ F_INT4EQ,		2, (FmgrFunction) int4eq },
	{ F_INT4LT,		2, (FmgrFunction) int4lt },
	{ F_TEXTEQ,		2, (FmgrFunction) texteq },
	{ F_XIDEQ,		2, (FmgrFunction) TransactionIdEquals },
	{ F_CIDEQ,		2, (FmgrFunction) int4eq },
	{ F_CHARNE,		2, (FmgrFunction) charne },
	{ F_CHARLT,		2, (FmgrFunction) charlt },
	{ F_CHARLE,		2, (FmgrFunction) charle },
	{ F_CHARGT,		2, (FmgrFunction) chargt },
	{ F_CHARGE,		2, (FmgrFunction) charge },
	{ F_CHARPL,		2, (FmgrFunction) charpl },
	{ F_CHARMI,		2, (FmgrFunction) charmi },
	{ F_CHARMUL,		2, (FmgrFunction) charmul },
	{ F_CHARDIV,		2, (FmgrFunction) chardiv },
#ifdef FMGR_ADT
	{ F_CHAR16REGEXEQ,	2, (FmgrFunction) char16regexeq },
	{ F_CHAR16REGEXNE,	2, (FmgrFunction) char16regexne },
	{ F_TEXTREGEXEQ,	2, (FmgrFunction) textregexeq },
	{ F_TEXTREGEXNE,	2, (FmgrFunction) textregexne },
#endif /* FMGR_ADT */

	{ F_RTSEL, 		7, (FmgrFunction) rtsel },
	{ F_RTNPAGE, 		7, (FmgrFunction) rtnpage },
	/*
	 * btree selectivity functions
	 */
	{ F_BTREESEL, 		7, (FmgrFunction) btreesel },
	{ F_BTREENPG, 		7, (FmgrFunction) btreenpage },

	{ F_EQSEL, 		5, (FmgrFunction) eqsel },
	{ F_NEQSEL, 		5, (FmgrFunction) neqsel },
	{ F_INTLTSEL, 		5, (FmgrFunction) intltsel },
	{ F_INTGTSEL, 		5, (FmgrFunction) intgtsel },
	{ F_EQJOINSEL, 		5, (FmgrFunction) eqjoinsel },
	{ F_NEQJOINSEL, 	5, (FmgrFunction) neqjoinsel },
	{ F_INTLTJOINSEL, 	5, (FmgrFunction) intltjoinsel },
	{ F_INTGTJOINSEL, 	5, (FmgrFunction) intgtjoinsel },

#ifdef FMGR_ADT
	{ F_POINT_IN,		1, (FmgrFunction) point_in },
	{ F_POINT_OUT,		1, (FmgrFunction) point_out },
	{ F_LSEG_IN,		1, (FmgrFunction) lseg_in },
	{ F_LSEG_OUT,		1, (FmgrFunction) lseg_out },
	{ F_PATH_IN,		1, (FmgrFunction) path_in },
	{ F_PATH_OUT,		1, (FmgrFunction) path_out },
	{ F_BOX_IN,		1, (FmgrFunction) box_in },
	{ F_BOX_OUT,		1, (FmgrFunction) box_out },
	{ F_BOX_OVERLAP,	2, (FmgrFunction) box_overlap },
	{ F_BOX_GE,		2, (FmgrFunction) box_ge },
	{ F_BOX_GT,		2, (FmgrFunction) box_gt },
	{ F_BOX_EQ,		2, (FmgrFunction) box_eq },
	{ F_BOX_LT,		2, (FmgrFunction) box_lt },
	{ F_BOX_LE,		2, (FmgrFunction) box_le },
	/*
	 *  F_BOX_SAME appears below -- no room here
	 */
	{ F_POINT_ABOVE,	2, (FmgrFunction) point_above },
	{ F_POINT_LEFT,		2, (FmgrFunction) point_left },
	{ F_POINT_RIGHT,	2, (FmgrFunction) point_right },
	{ F_POINT_BELOW,	2, (FmgrFunction) point_below },
	{ F_POINT_EQ,		2, (FmgrFunction) point_eq },
	{ F_ON_PB,		2, (FmgrFunction) on_pb },
	{ F_ON_PPATH,		2, (FmgrFunction) on_ppath },
	{ F_BOX_CENTER,		1, (FmgrFunction) box_center },
	{ F_AREASEL, 		5, (FmgrFunction) areasel },
	{ F_AREAJOINSEL, 	5, (FmgrFunction) areajoinsel },
#endif /* FMGR_ADT */
	{ F_INT4MUL,		2, (FmgrFunction) int4mul },
#ifdef FMGR_MATH
	{ F_INT4FAC,		1, (FmgrFunction) int4fac },
#endif /* FMGR_MATH */
#ifdef FMGR_ADT
	{ F_POINTDIST,		2, (FmgrFunction) pointdist },
#endif /* FMGR_ADT */
	{ F_INT4NE,		2, (FmgrFunction) int4ne },
	{ F_INT2NE,		2, (FmgrFunction) int2ne },
	{ F_INT2GT,		2, (FmgrFunction) int2gt },
	{ F_INT4GT,		2, (FmgrFunction) int4gt },
	{ F_INT2LE,		2, (FmgrFunction) int2le },
	{ F_INT4LE,		2, (FmgrFunction) int4le },
	{ F_INT4GE,		2, (FmgrFunction) int4ge },
	{ F_INT2GE,		2, (FmgrFunction) int2ge },
	{ F_INT2MUL,		2, (FmgrFunction) int2mul },
	{ F_INT2DIV,		2, (FmgrFunction) int2div },
	{ F_INT4DIV,		2, (FmgrFunction) int4div },
#ifdef FMGR_MATH
	{ F_INT2MOD,		2, (FmgrFunction) int2mod },
	{ F_INT4MOD,		2, (FmgrFunction) int4mod },
#endif /* FMGR_MATH */
	{ F_TEXTNE,		2, (FmgrFunction) textne },
	{ F_INT24EQ,		2, (FmgrFunction) int4eq },
	{ F_INT42EQ,		2, (FmgrFunction) int4eq },
	{ F_INT24LT,		2, (FmgrFunction) int4lt },
	{ F_INT42LT,		2, (FmgrFunction) int4lt },
	{ F_INT24GT,		2, (FmgrFunction) int4gt },
	{ F_INT42GT,		2, (FmgrFunction) int4gt },
	{ F_INT24NE,		2, (FmgrFunction) int4ne },
	{ F_INT42NE,		2, (FmgrFunction) int4ne },
	{ F_INT24LE,		2, (FmgrFunction) int4le },
	{ F_INT42LE,		2, (FmgrFunction) int4le },
	{ F_INT24GE,		2, (FmgrFunction) int4ge },
	{ F_INT42GE,		2, (FmgrFunction) int4ge },
	{ F_INT24MUL,		2, (FmgrFunction) int4mul },
	{ F_INT42MUL,		2, (FmgrFunction) int4mul },
	{ F_INT24DIV,		2, (FmgrFunction) int4div },
	{ F_INT42DIV,		2, (FmgrFunction) int4div },
#ifdef FMGR_MATH
	{ F_INT24MOD,		2, (FmgrFunction) int4mod },
	{ F_INT42MOD,		2, (FmgrFunction) int4mod },
#endif /* FMGR_MATH */
	{ F_INT2PL,		2, (FmgrFunction) int2pl },
	{ F_INT4PL,		2, (FmgrFunction) int4pl },
	{ F_INT24PL,		2, (FmgrFunction) int4pl },
	{ F_INT42PL,		2, (FmgrFunction) int4pl },
	{ F_INT2MI,		2, (FmgrFunction) int2mi },
	{ F_INT4MI,		2, (FmgrFunction) int4mi },
	{ F_INT24MI,		2, (FmgrFunction) int4mi },
	{ F_INT42MI,		2, (FmgrFunction) int4mi },
	{ F_OIDEQ,		2, (FmgrFunction) int4eq },
	{ F_OIDNE,		2, (FmgrFunction) int4ne },
#ifdef FMGR_ADT
	{ F_BOX_SAME,		2, (FmgrFunction) box_same },
	{ F_BOX_CONTAIN,	2, (FmgrFunction) box_contain },
	{ F_BOX_LEFT,		2, (FmgrFunction) box_left },
	{ F_BOX_OVERLEFT,	2, (FmgrFunction) box_overleft },
	{ F_BOX_OVERRIGHT,	2, (FmgrFunction) box_overright },
	{ F_BOX_RIGHT,		2, (FmgrFunction) box_right },
	{ F_BOX_CONTAINED,	2, (FmgrFunction) box_contained },
	{ F_RT_BOX_UNION,	2, (FmgrFunction) rt_box_union },
	{ F_RT_BOX_INTER,	2, (FmgrFunction) rt_box_inter },
	{ F_RT_BOX_SIZE,	1, (FmgrFunction) rt_box_size },
	{ F_RT_BIGBOX_SIZE,	1, (FmgrFunction) rt_bigbox_size },
	{ F_RT_POLY_UNION,	2, (FmgrFunction) rt_poly_union },
	{ F_RT_POLY_INTER,	2, (FmgrFunction) rt_poly_inter },
	{ F_RT_POLY_SIZE,	1, (FmgrFunction) rt_poly_size },
#endif /* FMGR_ADT */
	{ F_FLOAT4IN,		1, (FmgrFunction) float4in },
	{ F_FLOAT4OUT,		1, (FmgrFunction) float4out },
	{ F_FLOAT4MUL,		2, (FmgrFunction) float4mul },
	{ F_FLOAT4DIV,		2, (FmgrFunction) float4div },
	{ F_FLOAT4PL,		2, (FmgrFunction) float4pl },
	{ F_FLOAT4MI,		2, (FmgrFunction) float4mi },
	{ F_FLOAT4UM,		1, (FmgrFunction) float4um },
	{ F_FLOAT4ABS,		1, (FmgrFunction) float4abs },
	{ F_FLOAT4INC,		1, (FmgrFunction) float4inc },
	{ F_FLOAT4LARGER,	2, (FmgrFunction) float4larger },
	{ F_FLOAT4SMALLER,	2, (FmgrFunction) float4smaller },
	{ F_FLOAT8IN,		1, (FmgrFunction) float8in },
	{ F_FLOAT8OUT,		1, (FmgrFunction) float8out },
	{ F_FLOAT8MUL,		2, (FmgrFunction) float8mul },
	{ F_FLOAT8DIV,		2, (FmgrFunction) float8div },
	{ F_FLOAT8PL,		2, (FmgrFunction) float8pl },
	{ F_FLOAT8MI,		2, (FmgrFunction) float8mi },
	{ F_FLOAT8UM,		1, (FmgrFunction) float8um },
	{ F_FLOAT8ABS,		1, (FmgrFunction) float8abs },
	{ F_FLOAT8INC,		1, (FmgrFunction) float8inc },
	{ F_FLOAT8LARGER,	2, (FmgrFunction) float8larger },
	{ F_FLOAT8SMALLER,	2, (FmgrFunction) float8smaller },
#ifdef FMGR_MATH
	{ F_DROUND,		1, (FmgrFunction) dround },
	{ F_DTRUNC,		1, (FmgrFunction) dtrunc },
	{ F_DSQRT,		1, (FmgrFunction) dsqrt },
	{ F_DCBRT,		1, (FmgrFunction) dcbrt },
	{ F_DPOW,		2, (FmgrFunction) dpow },
	{ F_DEXP,		1, (FmgrFunction) dexp },
	{ F_DLOG,		1, (FmgrFunction) dlog1 },
#endif /* FMGR_MATH */
	{ F_ABSTIMEIN,		1, (FmgrFunction) abstimein },
	{ F_ABSTIMEOUT,		1, (FmgrFunction) abstimeout },
	{ F_RELTIMEIN,		1, (FmgrFunction) reltimein },
	{ F_RELTIMEOUT,		1, (FmgrFunction) reltimeout },
	{ F_TIMEPL,			1, (FmgrFunction) timepl },
	/*
	 * XXX Intervening slots reserved for time constructs --
	 *     they will not be user-callable until version 2.
	 */
	{ F_ABSTIMEEQ,		2, (FmgrFunction) abstimeeq },
	{ F_ABSTIMENE,		2, (FmgrFunction) abstimene },
	{ F_ABSTIMELT,		2, (FmgrFunction) abstimelt },
	{ F_ABSTIMEGT,		2, (FmgrFunction) abstimegt },
	{ F_ABSTIMELE,		2, (FmgrFunction) abstimele },
	{ F_ABSTIMEGE,		2, (FmgrFunction) abstimege },
#ifdef FMGR_MATH
	{ F_INT2FAC,		1, (FmgrFunction) int2fac },
	{ F_FLOAT48MUL,		2, (FmgrFunction) float48mul },
	{ F_FLOAT48DIV,		2, (FmgrFunction) float48div },
	{ F_FLOAT48PL,		2, (FmgrFunction) float48pl },
	{ F_FLOAT48MI,		2, (FmgrFunction) float48mi },
	{ F_FLOAT84MUL,		2, (FmgrFunction) float84mul },
	{ F_FLOAT84DIV,		2, (FmgrFunction) float84div },
	{ F_FLOAT84PL,		2, (FmgrFunction) float84pl },
	{ F_FLOAT84MI,		2, (FmgrFunction) float84mi },
	{ F_FLOAT4EQ,		2, (FmgrFunction) float4eq },
	{ F_FLOAT4NE,		2, (FmgrFunction) float4ne },
	{ F_FLOAT4LT,		2, (FmgrFunction) float4lt },
	{ F_FLOAT4LE,		2, (FmgrFunction) float4le },
	{ F_FLOAT4GT,		2, (FmgrFunction) float4gt },
	{ F_FLOAT4GE,		2, (FmgrFunction) float4ge },
	{ F_FLOAT8EQ,		2, (FmgrFunction) float8eq },
	{ F_FLOAT8NE,		2, (FmgrFunction) float8ne },
	{ F_FLOAT8LT,		2, (FmgrFunction) float8lt },
	{ F_FLOAT8LE,		2, (FmgrFunction) float8le },
	{ F_FLOAT8GT,		2, (FmgrFunction) float8gt },
	{ F_FLOAT8GE,		2, (FmgrFunction) float8ge },
	{ F_FLOAT48EQ,		2, (FmgrFunction) float48eq },
	{ F_FLOAT48NE,		2, (FmgrFunction) float48ne },
	{ F_FLOAT48LT,		2, (FmgrFunction) float48lt },
	{ F_FLOAT48LE,		2, (FmgrFunction) float48le },
	{ F_FLOAT48GT,		2, (FmgrFunction) float48gt },
	{ F_FLOAT48GE,		2, (FmgrFunction) float48ge },
	{ F_FLOAT84EQ,		2, (FmgrFunction) float84eq },
	{ F_FLOAT84NE,		2, (FmgrFunction) float84ne },
	{ F_FLOAT84LT,		2, (FmgrFunction) float84lt },
	{ F_FLOAT84LE,		2, (FmgrFunction) float84le },
	{ F_FLOAT84GT,		2, (FmgrFunction) float84gt },
	{ F_FLOAT84GE,		2, (FmgrFunction) float84ge },
#endif /* FMGR_MATH */
	{ F_F4TOF8,		2, (FmgrFunction) ftod },
	{ F_F8TOF4,		2, (FmgrFunction) dtof },
	{ F_I2TOI4,		2, (FmgrFunction) itoi },
	{ F_I4TOI2,		2, (FmgrFunction) itoi },
	{ F_KEYFIRSTEQ,		2, (FmgrFunction) keyfirsteq },

	/* no room for this above */
	{ F_RTINSERT,		3, (FmgrFunction) rtinsert },
	{ F_RTDELETE,		2, (FmgrFunction) rtdelete },
	{ F_RTGETTUPLE, 	6, (FmgrFunction) rtgettuple },
	{ F_RTBUILD, 		8, (FmgrFunction) rtbuild },
	{ F_RTBEGINSCAN, 	4, (FmgrFunction) rtbeginscan },
	{ F_RTENDSCAN,		1, (FmgrFunction) rtendscan },
	{ F_RTMARKPOS,		1, (FmgrFunction) rtmarkpos },
	{ F_RTRESTRPOS,		1, (FmgrFunction) rtrestrpos },
	{ F_RTRESCAN,		3, (FmgrFunction) rtrescan },

	/* new btrees */
	{ F_NBTGETTUPLE,	6, (FmgrFunction) btgettuple },
	{ F_NBTINSERT,		3, (FmgrFunction) btinsert },
	{ F_NBTDELETE,		2, (FmgrFunction) btdelete },
	{ F_NBTBEGINSCAN,	4, (FmgrFunction) btbeginscan },
	{ F_NBTRESCAN,		3, (FmgrFunction) btrescan },
	{ F_NBTENDSCAN,		1, (FmgrFunction) btendscan },
	{ F_NBTMARKPOS,		1, (FmgrFunction) btmarkpos },
	{ F_NBTRESTRPOS,	1, (FmgrFunction) btrestrpos },
	{ F_NBTBUILD,		8, (FmgrFunction) btbuild },
#ifdef FMGR_ADT
	{ F_POLY_SAME,		2, (FmgrFunction) poly_same },
	{ F_POLY_CONTAIN,	2, (FmgrFunction) poly_contain },
	{ F_POLY_LEFT,		2, (FmgrFunction) poly_left },
	{ F_POLY_OVERLEFT,	2, (FmgrFunction) poly_overleft },
	{ F_POLY_OVERRIGHT,	2, (FmgrFunction) poly_overright },
	{ F_POLY_RIGHT,		2, (FmgrFunction) poly_right },
	{ F_POLY_CONTAINED,	2, (FmgrFunction) poly_contained },
	{ F_POLY_OVERLAP,	2, (FmgrFunction) poly_overlap },
	{ F_POLY_IN,		1, (FmgrFunction) poly_in },
	{ F_POLY_OUT,		1, (FmgrFunction) poly_out },
#endif /* FMGR_ADT */
	/* per-opclass comparison functions for new btrees */
	{ F_BTINT2CMP,		2, (FmgrFunction) btint2cmp },
	{ F_BTINT4CMP,		2, (FmgrFunction) btint4cmp },
	{ F_BTINT42CMP,		2, (FmgrFunction) btint42cmp },
	{ F_BTINT24CMP,		2, (FmgrFunction) btint24cmp },
	{ F_BTFLOAT4CMP,	2, (FmgrFunction) btfloat4cmp },
	{ F_BTFLOAT8CMP,	2, (FmgrFunction) btfloat8cmp },
	{ F_BTOIDCMP,		2, (FmgrFunction) btoidcmp },
	{ F_BTABSTIMECMP,	2, (FmgrFunction) btabstimecmp },
	{ F_BTCHARCMP,		2, (FmgrFunction) btcharcmp },
	{ F_BTCHAR16CMP,	2, (FmgrFunction) btchar16cmp },
	{ F_BTTEXTCMP,		2, (FmgrFunction) bttextcmp },

	{ F_INT4NOTIN, 		4, (FmgrFunction) int4notin },
	{ F_OIDNOTIN, 		4, (FmgrFunction) oidnotin },
	{ F_INT44IN,		1, (FmgrFunction) int44in },
	{ F_INT44OUT,		1, (FmgrFunction) int44out },
	{ F_GETATTRIBUTE,	1, (FmgrFunction) GetAttribute },

	{ F_CHAR16LT,		2, (FmgrFunction) char16lt },
	{ F_CHAR16LE,		2, (FmgrFunction) char16le },
	{ F_CHAR16GT,		2, (FmgrFunction) char16gt },
	{ F_CHAR16GE,		2, (FmgrFunction) char16ge },
	{ F_CHAR16NE,		2, (FmgrFunction) char16ne },

	{ F_LOCKADD,		2, (FmgrFunction) prs2LockUnion },
	{ F_LOCKRM,		2, (FmgrFunction) prs2RemoveAllLocksOfRule },
	{ F_PG_USERNAME,	0, (FmgrFunction) pg_username },
	{ F_USERFNTEST,		1, (FmgrFunction) userfntest },
	{ F_BYTEASIZE,		1, (FmgrFunction) byteaGetSize },
	{ F_BYTEAGETBYTE,	2, (FmgrFunction) byteaGetByte },
	{ F_BYTEASETBYTE,	3, (FmgrFunction) byteaSetByte },
	{ F_BYTEAGETBIT,	2, (FmgrFunction) byteaGetBit },
	{ F_BYTEASETBIT,	3, (FmgrFunction) byteaSetBit },
	{ F_PQTEST,		1, (FmgrFunction) pqtest },

	{ F_TEXTLT,		2, (FmgrFunction) text_lt },
	{ F_TEXTLE,		2, (FmgrFunction) text_le },
	{ F_TEXTGT,		2, (FmgrFunction) text_gt },
 	{ F_TEXTGE,		2, (FmgrFunction) text_ge },
	{ F_ARRAY_IN,	2, (FmgrFunction) array_in },
	{ F_ARRAY_OUT,	2, (FmgrFunction) array_out },
	{ F_FILENAME_IN,2, (FmgrFunction) filename_in },
	{ F_FILENAME_OUT,2, (FmgrFunction) filename_out },

	{ F_SMGRIN, 1, (FmgrFunction) smgrin },
	{ F_SMGROUT, 1, (FmgrFunction) smgrout },
	{ F_SMGREQ, 2, (FmgrFunction) smgreq },
	{ F_SMGRNE, 2, (FmgrFunction) smgrne },

	{ F_LO_FILEIN,  1, (FmgrFunction) lo_filein },
	{ F_LO_FILEOUT, 1, (FmgrFunction) lo_fileout},
	{ F_INT4INC,    1, (FmgrFunction) int4inc},
	{ F_INT2INC,    1, (FmgrFunction) int2inc},
	{ F_INT4LARGER, 2, (FmgrFunction) int4larger},
	{ F_INT4SMALLER,2, (FmgrFunction) int4smaller},
	{ F_INT2LARGER, 2, (FmgrFunction) int2larger},
	{ F_INT2SMALLER,2, (FmgrFunction) int2smaller},

#ifdef NOBTREE

	{ F_NOBTGETTUPLE,	6, (FmgrFunction) nobtgettuple },
	{ F_NOBTINSERT,		3, (FmgrFunction) nobtinsert },
	{ F_NOBTDELETE,		2, (FmgrFunction) nobtdelete },
	{ F_NOBTBEGINSCAN,	4, (FmgrFunction) nobtbeginscan },
	{ F_NOBTRESCAN,		3, (FmgrFunction) nobtrescan },
	{ F_NOBTENDSCAN,	1, (FmgrFunction) nobtendscan },
	{ F_NOBTMARKPOS,	1, (FmgrFunction) nobtmarkpos },
	{ F_NOBTRESTRPOS,	1, (FmgrFunction) nobtrestrpos },
	{ F_NOBTBUILD,		8, (FmgrFunction) nobtbuild },

#endif /* NOBTREE */

	{ F_FIMPORT,	1, (FmgrFunction) fimport },
	{ F_FEXPORT,	2, (FmgrFunction) fexport },
	{ F_FABSTRACT,	5, (FmgrFunction) fabstract },
	{ F_OIDSEQLT,	2, (FmgrFunction) oidseqlt },
	{ F_OIDSEQLE,	2, (FmgrFunction) oidseqle },
	{ F_OIDSEQEQ,	2, (FmgrFunction) oidseqeq },
	{ F_OIDSEQGE,	2, (FmgrFunction) oidseqge },
	{ F_OIDSEQGT,	2, (FmgrFunction) oidseqgt },
	{ F_OIDSEQNE,	2, (FmgrFunction) oidseqne },
	{ F_OIDSEQCMP,	2, (FmgrFunction) oidseqcmp },
	{ F_MKOIDSEQ,	2, (FmgrFunction) mkoidseq },

        { F_FILETOOID,          1, (FmgrFunction) FilenameToOID },
        { F_LOCREATOID,         1, (FmgrFunction) LOcreatOID },
        { F_LOOPEN,             2, (FmgrFunction) LOopen },
        { F_LOCLOSE,            1, (FmgrFunction) LOclose },
        { F_LOREAD,             2, (FmgrFunction) LOread },
        { F_LOWRITE,            2, (FmgrFunction) LOwrite },
        { F_LOLSEEK,            3, (FmgrFunction) LOlseek },
        { F_LOCREAT,            2, (FmgrFunction) LOcreat },
        { F_LOTELL,             1, (FmgrFunction) LOtell },
        { F_LOFTRUNCATE,        2, (FmgrFunction) LOftruncate },
        { F_LOSTAT,             1, (FmgrFunction) LOstat },
        { F_LORENAME,           2, (FmgrFunction) LOrename },
        { F_LOMKDIR,            2, (FmgrFunction) LOmkdir },
        { F_LORMDIR,            1, (FmgrFunction) LOrmdir },
        { F_LOUNLINK,           1, (FmgrFunction) LOunlink }
};

static 	n_builtins = lengthof(builtins);

char *c_lang_func_call_ptr(user_fn,n_arguments,values)
	int 		n_arguments;
	FmgrValues	values;
	func_ptr	user_fn;
{
    char		*returnValue = NULL;
    switch(n_arguments)
	{
	case 0:
	    returnValue = (*user_fn)();
	    break;
	case 1:
	    returnValue = (*user_fn)
		(values.data[0]);
	    break;
	case 2:
	    returnValue = (*user_fn)
		(values.data[0],
		 values.data[1]);
	    break;
	case 3:
	    returnValue = (*user_fn)
		(values.data[0],
		 values.data[1],
		 values.data[2]);
	    break;
	case 4:
	    returnValue = (*user_fn)
		(values.data[0],
		 values.data[1],
		 values.data[2],
		 values.data[3]);
	    break;
	case 5:
	    returnValue = (*user_fn)
		(values.data[0],
		 values.data[1],
		 values.data[2],
		 values.data[3],
		 values.data[4]);
	    break;
	case 6:
	    returnValue = (*user_fn)
		(values.data[0],
		 values.data[1],
		 values.data[2],
		 values.data[3],
		 values.data[4],
		 values.data[5]);
	    break;
	case 7:
	    returnValue = (*user_fn)
		(values.data[0],
		 values.data[1],
		 values.data[2],
		 values.data[3],
		 values.data[4],
		 values.data[5],
		 values.data[6]);
	    break;
	case 8:
	    returnValue = (*user_fn)
		(values.data[0],
		 values.data[1],
		 values.data[2],
		 values.data[3],
		 values.data[4],
		 values.data[5],
		 values.data[6],
		 values.data[7]);
	    break;
	case 9:
	    returnValue = (*user_fn)
		(values.data[0],
		 values.data[1],
		 values.data[2],
		 values.data[3],
		 values.data[4],
		 values.data[5],
		 values.data[6],
		 values.data[7],
		 values.data[8]);
	    break;
	case 10:
	    returnValue = (*user_fn)
		(values.data[0],
		 values.data[1],
		 values.data[2],
		 values.data[3],
		 values.data[4],
		 values.data[5],
		 values.data[6],
		 values.data[7],
		 values.data[8],
		 values.data[9]);
	    break;
	default:
	    elog(WARN, "c_lang_call_ptr: too many args to function!");
	    break; /* Not really necessary, but why not? */
	}
    return(returnValue);
}

char *c_lang_func_call_ptr_array(user_fn,nargs,args)
     int 		nargs;
     char *args[];
     func_ptr	user_fn;

{
    char *returnValue;
    switch (nargs)
	{
	case 0:
	    returnValue = (*user_fn)();
	    break;
	case 1:
	    returnValue = (*user_fn)
		(args[0]);
	    break;
	case 2:
	    returnValue = (*user_fn)
		(args[0],
		 args[1]);
	    break;
	case 3:
	    returnValue = (*user_fn)
		(args[0],
		 args[1],
		 args[2]);
	    break;
	case 4:
	    returnValue = (*user_fn)
		(args[0],
		 args[1],
		 args[2],
		 args[3]);
	    break;
	case 5:
	    returnValue = (*user_fn)
		(args[0],
		 args[1],
		 args[2],
		 args[3],
		 args[4]);
	    break;
	case 6:
	    returnValue = (*user_fn)
		(args[0],
		 args[1],
		 args[2],
		 args[3],
		 args[4],
		 args[5]);
	    break;
	case 7:
	    returnValue = (*user_fn)
		(args[0],
		 args[1],
		 args[2],
		 args[3],
		 args[4],
		 args[5],
		 args[6]);
	    break;
	case 8:
	    returnValue = (*user_fn)
		(args[0],
		 args[1],
		 args[2],
		 args[3],
		 args[4],
		 args[5],
		 args[6],
		 args[7]);
	    break;
	case 9:
	    returnValue = (*user_fn)
		(args[0],
		 args[1],
		 args[2],
		 args[3],
		 args[4],
		 args[5],
		 args[6],
		 args[7],
		 args[8]);
	    break;
	case 10:
	    returnValue = (*user_fn)
		(args[0],
		 args[1],
		 args[2],
		 args[3],
		 args[4],
		 args[5],
		 args[6],
		 args[7],
		 args[8],
		 args[9]);
	    break;
	default:
	    elog(WARN, "fmgr: too many args to function");
	    break; /* Not really necessary, but why not? */
	}
    return(returnValue);
}
char *postquel_lang_func_call_array(procedureId,pronargs,args)
     ObjectId procedureId;
     int	pronargs;
     char *args[];    
{
    List query_descriptor = LispNil, qd = LispNil;
    HeapTuple   procedureTuple;
    ParamListInfo paramlist;
    char *plan_str;
    int status,x;
    Datum *value;
    Boolean *isnull;
    

    plan_str = (char *)
	SearchSysCacheGetAttribute(PROOID,Anum_pg_proc_prosrc, procedureId);
    qd = StringToPlanWithParams(textout((struct varlena *)plan_str),&paramlist);
    x=0; 
    while(paramlist[x].kind != PARAM_INVALID) {
	paramlist[x].value = (Datum) args[x];
	x++;
    }
    if (prs2RunOnePlanAndGetValue(qd,paramlist, NULL, &value, &isnull))
	return (char *) value;
    else return (char *)NULL;
}
char *postquel_lang_func_call(procedureId,pronargs,values)
     ObjectId procedureId;
     int	pronargs;
     FmgrValues	values;
{


    
}






ObjectId fmgr_func_lang(procedureId)
     ObjectId procedureId;
{
    HeapTuple   procedureTuple;
    ObjectId language;
    int low, high,i;

    low = 0;
    high = n_builtins;
    while (low <= high) {
	i = low + (high - low) / 2;
	if (procedureId == builtins[i].proid)
	    break;
	else if (procedureId > builtins[i].proid)
	    low = i + 1;
	else
	    high = i - 1;
    }

	/*
	 * If we found the procedure in the above loop, wonderful.  Otherwise,
	 * it could be a 'language' procedure
	 * it is a dynamically loaded function - get its pointer and number
	 * of arguments from fmgr_dynamic().
	 */
    if (procedureId == builtins[i].proid) return INTERNALlanguageId;

    procedureTuple = SearchSysCacheTuple(PROOID, (char *) procedureId,
					 NULL, NULL, NULL);
    if (!HeapTupleIsValid(procedureTuple)) {
	elog(WARN, "fmgr: Cache lookup failed for procedure %d\n",
	     procedureId);
	return(NULL);
    }
    language = ((struct proc *) GETSTRUCT(procedureTuple))->prolang;
    return language;
}

void fmgr_info(procedureId, function, nargs)
     ObjectId procedureId;
     func_ptr *function;
     int	*nargs;
{
	int low, high, i;

	int arg_count;
	func_ptr user_fn, fmgr_dynamic();

	/*
	 * Binary-search the function array for the appropriate procedure.
	 */

	low = 0;
	high = n_builtins;
	while (low <= high) {
		i = low + (high - low) / 2;
		if (procedureId == builtins[i].proid)
			break;
		else if (procedureId > builtins[i].proid)
			low = i + 1;
		else
			high = i - 1;
	}

	/*
	 * If we found the procedure in the above loop, wonderful.  Otherwise,
	 * it could be a 'language' procedure
	 * it is a dynamically loaded function - get its pointer and number
	 * of arguments from fmgr_dynamic().
	 */

	if (procedureId != builtins[i].proid) {
	    HeapTuple   procedureTuple;
	    struct proc *procedureStruct;
	    ObjectId language;

	    procedureTuple = SearchSysCacheTuple(PROOID, (char *) procedureId,
						 NULL, NULL, NULL);
	    if (!HeapTupleIsValid(procedureTuple)) {
		elog(WARN, "fmgr: Cache lookup failed for procedure %d\n",
		     procedureId);
	    }
	    procedureStruct = (struct proc *) GETSTRUCT(procedureTuple);
	    language = procedureStruct->prolang;
	    switch (language) {
	    case INTERNALlanguageId:
		elog(WARN,
		     "internal procedure %d is not in the 'builtins' table",
		     procedureId);
		break;
	    case ClanguageId:
		user_fn = fmgr_dynamic(procedureId, nargs);
		break;
	    case POSTQUELlanguageId:
		user_fn = NULL;
		*nargs = procedureStruct->pronargs;
		break;
	    default:
		elog(WARN,
		     "procedure %d is of an unknown language %d",
		     procedureId, language);
	    }
	}
	else
	{
		user_fn = builtins[i].func;
		*nargs = builtins[i].nargs;
	}
	*function = user_fn;
}

/*
 *	fmgr		- return the value of a function call
 *
 *	If the function is a system routine, it's compiled in, so call
 *	it directly.
 *
 *      Otherwise pass it to the the appropriate 'language' function caller.
 *
 *	Returns the return value of the invoked function if succesful,
 *	0 if unsuccessful.
 *
 */
char *
fmgr(va_alist)
	va_dcl
{
	va_list		pvar;
	register	i, j;
	ObjectId	procedureId;
	int 		pronargs;
	FmgrValues	values;
	func_ptr	user_fn;

	va_start(pvar);
	procedureId = va_arg(pvar, ObjectId);

	fmgr_info(procedureId, &user_fn, &pronargs);

	if (pronargs > MAXFMGRARGS)
	{
		elog(WARN,
		    "fmgr: can\'t pass enough args to function: fid=%d",
		     procedureId); 
	}

	for (j = 0; j < pronargs; ++j)
		values.data[j] = va_arg(pvar, char *);

	va_end(pvar);
	switch (fmgr_func_lang(procedureId)) {
	case INTERNALlanguageId:
	case ClanguageId:
	    return c_lang_func_call_ptr(user_fn,pronargs,values);
	    break;
	case POSTQUELlanguageId:
	    return postquel_lang_func_call(procedureId,pronargs,values);
	    break;
	default:
	    elog(WARN,
		 "No function caller registered for language");
	}
}

char *
fmgr_array_args(procedureId, nargs, args)
    ObjectId procedureId;
	int nargs;
	char * args[];
{
	func_ptr user_fn;
	int true_arguments;
	char *returnValue;

	fmgr_info(procedureId, &user_fn, &true_arguments);
	switch (fmgr_func_lang(procedureId)) {
	case INTERNALlanguageId:
	case ClanguageId:
	    return c_lang_func_call_ptr_array(user_fn,true_arguments,args);
	    break;
	case POSTQUELlanguageId:
	    return postquel_lang_func_call_array(procedureId,
						 true_arguments,args);
	    break;
	default:
	    elog(WARN,
		 "No function caller for arrays args registered for language");
	}
}
	
/*
 * varargs
 * 
 * func_ptr, n_arguments, args...
 *
 */

char *
fmgr_by_ptr(va_alist)
	va_dcl
{
	va_list		pvar;
	FmgrValues	values;
	int			n_arguments, j;
	char		*returnValue = NULL;
	func_ptr	user_fn;

	va_start(pvar);

	user_fn = va_arg(pvar, func_ptr);
	n_arguments = va_arg(pvar, int);

	for (j = 0; j < n_arguments; ++j)
		values.data[j] = va_arg(pvar, char *);

	va_end(pvar);

	if (n_arguments > MAXFMGRARGS)
 	{
		elog(WARN,
		    "fmgr_by_ptr; can\'t pass enough args to function: nargs=%d",
		     n_arguments); 
	}
	return c_lang_func_call_ptr(user_fn,n_arguments,values);
}

char *
fmgr_by_ptr_array_args(user_fn, nargs, args)
     func_ptr user_fn;
     int nargs;
     char * args[];
{
	char *returnValue;
	return c_lang_func_call_ptr_array(user_fn,nargs,args);
    }
