diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 86a16ddb04fdc02b6f6442e065b1f7eb313905f3..4f234f62b94d81884da6cf1f56c7015c3ceb0062 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.53 2002/06/20 20:29:27 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.54 2002/07/18 04:40:30 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -759,6 +759,7 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
 	natts = tupdesc->natts;
 
 	dvalues = (Datum *) palloc(natts * sizeof(Datum));
+	nulls = (char *) palloc(natts * sizeof(char));
 
 	/* Call the "in" function for each attribute */
 	for (i = 0; i < natts; i++)
@@ -772,22 +773,18 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
 			dvalues[i] = FunctionCall3(&attinfuncinfo, CStringGetDatum(values[i]),
 										ObjectIdGetDatum(attelem),
 										Int32GetDatum(atttypmod));
+			nulls[i] = ' ';
 		}
 		else
+		{
 			dvalues[i] = PointerGetDatum(NULL);
+			nulls[i] = 'n';
+		}
 	}
 
 	/*
 	 * Form a tuple
 	 */
-	nulls = (char *) palloc(natts * sizeof(char));
-	for (i = 0; i < natts; i++)
-	{
-		if (DatumGetPointer(dvalues[i]) != NULL)
-			nulls[i] = ' ';
-		else
-			nulls[i] = 'n';
-	}
 	tuple = heap_formtuple(tupdesc, dvalues, nulls);
 
 	return tuple;
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index bd65c3911c756cb5200252f334d88fd75d3948db..a8d4e4fb5f599621d61e9e04646f9e16e1fc0bf5 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -52,7 +52,7 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
 		retval->call_cntr = 0;
 		retval->max_calls = 0;
 		retval->slot = NULL;
-		retval->fctx = NULL;
+		retval->user_fctx = NULL;
 		retval->attinmeta = NULL;
 		retval->fmctx = fcinfo->flinfo->fn_mcxt;
 
@@ -75,6 +75,23 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
 	return retval;
 }
 
+/*
+ * per_MultiFuncCall
+ * 
+ * Do Multi-function per-call setup
+ */
+FuncCallContext *
+per_MultiFuncCall(PG_FUNCTION_ARGS)
+{
+	FuncCallContext *retval = (FuncCallContext *) fcinfo->flinfo->fn_extra;
+
+	/* make sure we start with a fresh slot */
+	if(retval->slot != NULL)
+		ExecClearTuple(retval->slot);
+
+	return retval;
+}
+
 /*
  * end_MultiFuncCall
  * Clean up after init_MultiFuncCall
diff --git a/src/include/funcapi.h b/src/include/funcapi.h
index 351a7a420d7952cc2ff1bf5a4be8c5e700f2aa72..f00b93b865b518d9f0cc9cccd72f7dc77b9ae51e 100644
--- a/src/include/funcapi.h
+++ b/src/include/funcapi.h
@@ -65,22 +65,57 @@ typedef struct
  */
 typedef struct
 {
-	/* Number of times we've been called before */
+	/*
+	 * Number of times we've been called before.
+	 * 
+	 * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and
+	 * incremented for you every time SRF_RETURN_NEXT() is called.
+	 */
 	uint32			call_cntr;
 
-	/* Maximum number of calls */
+	/*
+	 * OPTIONAL maximum number of calls
+	 *
+	 * max_calls is here for convenience ONLY and setting it is OPTIONAL.
+	 * If not set, you must provide alternative means to know when the
+	 * function is done.
+	 */
 	uint32			max_calls;
 
-	/* pointer to result slot */
+	/*
+	 * OPTIONAL pointer to result slot
+	 * 
+	 * slot is for use when returning tuples (i.e. composite data types)
+	 * and is not needed when returning base (i.e. scalar) data types.
+	 */
 	TupleTableSlot *slot;
 
-	/* pointer to misc context info */
-	void		   *fctx;
-
-	/* pointer to struct containing arrays of attribute type input metainfo */
+	/*
+	 * OPTIONAL pointer to misc user provided context info
+	 * 
+	 * user_fctx is for use as a pointer to your own struct to retain
+	 * arbitrary context information between calls for your function.
+	 */
+	void		   *user_fctx;
+
+	/*
+	 * OPTIONAL pointer to struct containing arrays of attribute type input
+	 * metainfo
+	 * 
+	 * attinmeta is for use when returning tuples (i.e. composite data types)
+	 * and is not needed when returning base (i.e. scalar) data types. It
+	 * is ONLY needed if you intend to use BuildTupleFromCStrings() to create
+	 * the return tuple.
+	 */
 	AttInMetadata	   *attinmeta;
 
-	/* memory context used to initialize structure */
+	/*
+	 * memory context used to initialize structure
+	 *
+	 * fmctx is set by SRF_FIRSTCALL_INIT() for you, and used by
+	 * SRF_RETURN_DONE() for cleanup. It is primarily for internal use
+	 * by the API.
+	 */
 	MemoryContext	fmctx;
 
 }	FuncCallContext;
@@ -137,7 +172,7 @@ extern void get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem);
  * 	Datum				result;
  * 	<user defined declarations>
  * 
- * 	if(SRF_IS_FIRSTPASS())
+ * 	if(SRF_IS_FIRSTCALL())
  * 	{
  * 		<user defined code>
  * 		funcctx = SRF_FIRSTCALL_INIT();
@@ -148,7 +183,7 @@ extern void get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem);
  * 		<user defined code>
  *  }
  * 	<user defined code>
- * 	funcctx = SRF_PERCALL_SETUP(funcctx);
+ * 	funcctx = SRF_PERCALL_SETUP();
  * 	<user defined code>
  * 
  * 	if (funcctx->call_cntr < funcctx->max_calls)
@@ -167,14 +202,12 @@ extern void get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem);
 
 /* from funcapi.c */
 extern FuncCallContext *init_MultiFuncCall(PG_FUNCTION_ARGS);
+extern FuncCallContext *per_MultiFuncCall(PG_FUNCTION_ARGS);
 extern void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx);
 
-#define SRF_IS_FIRSTPASS() (fcinfo->flinfo->fn_extra == NULL)
+#define SRF_IS_FIRSTCALL() (fcinfo->flinfo->fn_extra == NULL)
 #define SRF_FIRSTCALL_INIT() init_MultiFuncCall(fcinfo)
-#define SRF_PERCALL_SETUP(_funcctx) \
-	fcinfo->flinfo->fn_extra; \
-	if(_funcctx->slot != NULL) \
-		ExecClearTuple(_funcctx->slot)
+#define SRF_PERCALL_SETUP() per_MultiFuncCall(fcinfo)
 #define SRF_RETURN_NEXT(_funcctx, _result) \
 	do { \
 		ReturnSetInfo	   *rsi; \