#!/bin/sh
#-------------------------------------------------------------------------
#
# Gen_fmgrtab.sh--
#    shell script to generate fmgr.h and fmgrtab.c from pg_proc.h
#
# Copyright (c) 1994, Regents of the University of California
#
#
# IDENTIFICATION
#    $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh.in,v 1.15 1999/04/09 22:35:41 tgl Exp $
#
# NOTES
#    Passes any -D options on to cpp prior to generating the list
#    of internal functions.  These come from BKIOPTS.
#
#-------------------------------------------------------------------------

if [ $? != 0 ]
then
	echo `basename $0`: Bad option
	exit 1
fi

BKIOPTS=''

#
# Pass on any -D declarations, throwing away any other command
# line switches.
#
for opt in $*
do
	case $opt in
	-D) BKIOPTS="$BKIOPTS -D$2"; shift; shift;;
	-D*) BKIOPTS="$BKIOPTS $1";shift;;
	--) shift; break;;
	-*) shift;;
	esac
done

INFILE=$1
RAWFILE=fmgr.raw
CPPTMPFILE=fmgrtmp.c
HFILE=fmgr.h
TABCFILE=fmgrtab.c

#
# Generate the file containing raw pg_proc tuple data
# (but only for "internal" language procedures...).
#
# Unlike genbki.sh, which can run through cpp last, we have to
# deal with preprocessor statements first (before we sort the
# function table by oid).
#
awk '
BEGIN		{ raw = 0; }
/^DATA/		{ print; next; }
/^BKI_BEGIN/	{ raw = 1; next; }
/^BKI_END/	{ raw = 0; next; }
raw == 1	{ print; next; }' $INFILE | \
sed 	-e 's/^.*OID[^=]*=[^0-9]*//' \
	-e 's/(//g' \
	-e 's/[ 	]*).*$//' | \
awk '
/^#/		{ print; next; }
$4 == "11"	{ print; next; }' > $CPPTMPFILE

@CPP@ $BKIOPTS $CPPTMPFILE | \
egrep '^[0-9]' | \
sort -n > $RAWFILE

rm -f $CPPTMPFILE

#
# Generate fmgr.h
#
cat > $HFILE <<FuNkYfMgRsTuFf
/*-------------------------------------------------------------------------
 *
 * $HFILE--
 *    Definitions for using internal procedures.
 *
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 * $Id: Gen_fmgrtab.sh.in,v 1.15 1999/04/09 22:35:41 tgl Exp $
 *
 * NOTES
 *	******************************
 *	*** DO NOT EDIT THIS FILE! ***
 *	******************************
 *
 *	It has been GENERATED by $0
 *	from $1
 *
 *-------------------------------------------------------------------------
 */
#ifndef	FMGR_H
#define FMGR_H

#include "postgres.h"

/*
 *	Maximum number of arguments for a built-in function.
 *
 *	XXX note that you cannot call a function with more than 8 
 *	    arguments from the user level since the catalogs only 
 *	    store 8 argument type values for type-checking ...
 */
#define	MAXFMGRARGS	9

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_c(FmgrInfo *finfo, FmgrValues *values, bool *isNull);
extern void fmgr_info(Oid procedureId, FmgrInfo *finfo);
extern char *fmgr(Oid procedureId, ... );
extern char *fmgr_ptr(FmgrInfo *finfo, ... );
extern char *fmgr_array_args(Oid procedureId, int nargs, 
			     char *args[], bool *isNull);

/*
 * defined in dfmgr.c
 */
extern func_ptr fmgr_dynamic(Oid procedureId, int *pronargs);
extern void load_file(char *filename);

/*
 *	For performance reasons, we often want to simply jump through a
 *	a function pointer (if it's valid, that is).  These calls have
 *	been macroized so we can run them through a routine that does
 *	sanity-checking (and so we can track them down more easily when
 *	we must).
 */

/* We don't make this static so fmgr_faddr() macros can access it */
FmgrInfo        *fmgr_pl_finfo;

#define fmgr_faddr(finfo) \
( \
	fmgr_pl_finfo = (finfo), \
	(func_ptr)(finfo)->fn_addr \
)

#ifdef TRACE_FMGR_PTR
#define	FMGR_PTR2(FINFO, ARG1, ARG2) \
	fmgr_ptr(FINFO, 2, ARG1, ARG2)
#else
#define	FMGR_PTR2(FINFO, ARG1, ARG2) \
( \
	((FINFO)->fn_addr) ? \
		(*(fmgr_faddr(FINFO)))(ARG1, ARG2) \
	: \
		fmgr((FINFO)->fn_oid, ARG1, ARG2) \
)
#endif

/*
 *	Flags for the builtin oprrest selectivity routines.
 */
#define	SEL_CONSTANT 	1	/* constant does not vary (not a parameter) */
#define	SEL_RIGHT	2 	/* constant appears to right of operator */

/*
 *	Constant macros for the OIDs of entries in pg_proc.
 *	NOTE: if the same "proname" is used for more than one
 *	internal-function entry in pg_proc, the equivalent macro
 *	will be defined with the lowest OID among those entries.
 */
FuNkYfMgRsTuFf

@TR@ @TRARGS@ < $RAWFILE | \
awk '
BEGIN	{ OFS = ""; }
	{ if (seenit[$2]++ == 0) print "#define F_", $2, " ", $1; }' >> $HFILE

cat >> $HFILE <<FuNkYfMgRsTuFf

#endif	/* FMGR_H */
FuNkYfMgRsTuFf

#
# Generate fmgr function table file.
#
# Print out the bogus function declarations, then the table that
# refers to them.
#
cat > $TABCFILE <<FuNkYfMgRtAbStUfF
/*-------------------------------------------------------------------------
 *
 * $TABCFILE--
 *    The function manager's table of internal functions.
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *    $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh.in,v 1.15 1999/04/09 22:35:41 tgl Exp $
 *
 * NOTES
 *
 *	******************************
 *	*** DO NOT EDIT THIS FILE! ***
 *	******************************
 *
 *	It has been GENERATED by $0
 *	from $1
 *
 *	We lie here to cc about the return type and arguments of the
 *	builtin functions; all ld cares about is the fact that it
 *	will need to resolve an external function reference.
 *
 *-------------------------------------------------------------------------
 */

#include <string.h>
#include <postgres.h>
#include "utils/fmgrtab.h"

FuNkYfMgRtAbStUfF

awk '{ print "extern char *", $(NF-1), "();"; }' $RAWFILE >> $TABCFILE

cat >> $TABCFILE <<FuNkYfMgRtAbStUfF

static FmgrCall fmgr_builtins[] = {
FuNkYfMgRtAbStUfF

awk '{ printf ("  {%d, %d, %s, \"%s\" },\n"), $1, $8, $(NF-1), $(NF-1) }' $RAWFILE >> $TABCFILE

cat >> $TABCFILE <<FuNkYfMgRtAbStUfF
  /* dummy entry is easier than getting rid of comma after last real one */
  { 0, 0, (func_ptr) NULL, NULL }
};

/* Note FMGR_NBUILTINS excludes the dummy entry */
#define FMGR_NBUILTINS  ((sizeof(fmgr_builtins) / sizeof(FmgrCall)) - 1)

FmgrCall *fmgr_isbuiltin(Oid id)
{
    int	low = 0;
    int	high = FMGR_NBUILTINS - 1;

    /* Loop invariant: low is the first index that could contain target
     * entry, and high is the last index that could contain it.
     */
	while (low <= high) {
		int i = (high + low) / 2;
		FmgrCall * ptr = &fmgr_builtins[i];
		if (id == ptr->proid)
			return ptr;
		else if (id > ptr->proid)
			low = i + 1;
		else
			high = i - 1;
	}
	return (FmgrCall *) NULL;
}

func_ptr fmgr_lookupByName(char *name) 
{
	/* Lookup a builtin by name.  Note there can be more than one entry in
	 * the array matching this name, but they should all point to the same
	 * routine.
	 */
    int i;
    for (i=0; i<FMGR_NBUILTINS; i++) {
		if (strcmp(name, fmgr_builtins[i].funcName) == 0)
			return fmgr_builtins[i].func;
    }
    return (func_ptr) NULL;
}

FuNkYfMgRtAbStUfF

rm -f $RAWFILE

# ----------------
#	all done
# ----------------
exit 0
