diff --git a/contrib/adminpack/adminpack.c b/contrib/adminpack/adminpack.c
index e697b5e2a900cdecb333c38a0ca1677543c5e305..879259ee03d2ba14c6b265895a567436b6f9c51a 100644
--- a/contrib/adminpack/adminpack.c
+++ b/contrib/adminpack/adminpack.c
@@ -8,7 +8,7 @@
  * Author: Andreas Pflug <pgadmin@pse-consulting.de>
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/contrib/adminpack/adminpack.c,v 1.10 2008/01/01 19:45:45 momjian Exp $
+ *	  $PostgreSQL: pgsql/contrib/adminpack/adminpack.c,v 1.11 2008/03/25 22:42:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,6 +23,7 @@
 #include "miscadmin.h"
 #include "postmaster/syslogger.h"
 #include "storage/fd.h"
+#include "utils/builtins.h"
 #include "utils/datetime.h"
 
 
@@ -68,11 +69,7 @@ typedef struct
 static char *
 convert_and_check_filename(text *arg, bool logAllowed)
 {
-	int			input_len = VARSIZE(arg) - VARHDRSZ;
-	char	   *filename = palloc(input_len + 1);
-
-	memcpy(filename, VARDATA(arg), input_len);
-	filename[input_len] = '\0';
+	char	   *filename = text_to_cstring(arg);
 
 	canonicalize_path(filename);	/* filename can change length here */
 
diff --git a/contrib/chkpass/chkpass.c b/contrib/chkpass/chkpass.c
index 18cac99ca6bf1c57bff0327d581dd2ff14d9c674..ed6a7566b25eef4db268a176110edc576ac62e65 100644
--- a/contrib/chkpass/chkpass.c
+++ b/contrib/chkpass/chkpass.c
@@ -4,7 +4,7 @@
  * darcy@druid.net
  * http://www.druid.net/darcy/
  *
- * $PostgreSQL: pgsql/contrib/chkpass/chkpass.c,v 1.19 2007/02/27 23:48:05 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/chkpass/chkpass.c,v 1.20 2008/03/25 22:42:41 tgl Exp $
  * best viewed with tabs set to 4
  */
 
@@ -17,6 +17,7 @@
 #endif
 
 #include "fmgr.h"
+#include "utils/builtins.h"
 
 PG_MODULE_MAGIC;
 
@@ -124,15 +125,8 @@ Datum
 chkpass_rout(PG_FUNCTION_ARGS)
 {
 	chkpass    *password = (chkpass *) PG_GETARG_POINTER(0);
-	text	   *result;
-	int			slen;
 
-	slen = strlen(password->password);
-	result = (text *) palloc(VARHDRSZ + slen);
-	SET_VARSIZE(result, VARHDRSZ + slen);
-	memcpy(VARDATA(result), password->password, slen);
-
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(password->password));
 }
 
 
@@ -145,13 +139,10 @@ Datum
 chkpass_eq(PG_FUNCTION_ARGS)
 {
 	chkpass    *a1 = (chkpass *) PG_GETARG_POINTER(0);
-	text	   *a2 = (text *) PG_GETARG_TEXT_P(1);
-	char		str[10];
-	int			sz;
+	text	   *a2 = PG_GETARG_TEXT_PP(1);
+	char		str[9];
 
-	sz = Min(VARSIZE(a2) - VARHDRSZ, 8);
-	memcpy(str, VARDATA(a2), sz);
-	str[sz] = '\0';
+	text_to_cstring_buffer(a2, str, sizeof(str));
 	PG_RETURN_BOOL(strcmp(a1->password, crypt(str, a1->password)) == 0);
 }
 
@@ -160,12 +151,9 @@ Datum
 chkpass_ne(PG_FUNCTION_ARGS)
 {
 	chkpass    *a1 = (chkpass *) PG_GETARG_POINTER(0);
-	text	   *a2 = (text *) PG_GETARG_TEXT_P(1);
-	char		str[10];
-	int			sz;
+	text	   *a2 = PG_GETARG_TEXT_PP(1);
+	char		str[9];
 
-	sz = Min(VARSIZE(a2) - VARHDRSZ, 8);
-	memcpy(str, VARDATA(a2), sz);
-	str[sz] = '\0';
+	text_to_cstring_buffer(a2, str, sizeof(str));
 	PG_RETURN_BOOL(strcmp(a1->password, crypt(str, a1->password)) != 0);
 }
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index e09d6f16f6973c037ad4f544566f51ee1efcb17d..a306a2a5af3a3c48f1b1b76967a5220b1848bbf0 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -8,7 +8,7 @@
  * Darko Prenosil <Darko.Prenosil@finteh.hr>
  * Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
  *
- * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.69 2008/01/14 02:49:47 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.70 2008/03/25 22:42:41 tgl Exp $
  * Copyright (c) 2001-2008, PostgreSQL Global Development Group
  * ALL RIGHTS RESERVED;
  *
@@ -116,8 +116,6 @@ typedef struct remoteConnHashEnt
 #define NUMCONN 16
 
 /* general utility */
-#define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))
-#define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
 #define xpfree(var_) \
 	do { \
 		if (var_ != NULL) \
@@ -171,7 +169,7 @@ typedef struct remoteConnHashEnt
 
 #define DBLINK_GET_CONN \
 	do { \
-			char *conname_or_str = GET_STR(PG_GETARG_TEXT_P(0)); \
+			char *conname_or_str = text_to_cstring(PG_GETARG_TEXT_PP(0)); \
 			rconn = getConnectionByName(conname_or_str); \
 			if(rconn) \
 			{ \
@@ -197,7 +195,7 @@ typedef struct remoteConnHashEnt
 
 #define DBLINK_GET_NAMED_CONN \
 	do { \
-			char *conname = GET_STR(PG_GETARG_TEXT_P(0)); \
+			char *conname = text_to_cstring(PG_GETARG_TEXT_PP(0)); \
 			rconn = getConnectionByName(conname); \
 			if(rconn) \
 				conn = rconn->conn; \
@@ -234,11 +232,11 @@ dblink_connect(PG_FUNCTION_ARGS)
 
 	if (PG_NARGS() == 2)
 	{
-		connstr = GET_STR(PG_GETARG_TEXT_P(1));
-		connname = GET_STR(PG_GETARG_TEXT_P(0));
+		connstr = text_to_cstring(PG_GETARG_TEXT_PP(1));
+		connname = text_to_cstring(PG_GETARG_TEXT_PP(0));
 	}
 	else if (PG_NARGS() == 1)
-		connstr = GET_STR(PG_GETARG_TEXT_P(0));
+		connstr = text_to_cstring(PG_GETARG_TEXT_PP(0));
 
 	oldcontext = MemoryContextSwitchTo(TopMemoryContext);
 
@@ -272,7 +270,7 @@ dblink_connect(PG_FUNCTION_ARGS)
 	else
 		pconn->conn = conn;
 
-	PG_RETURN_TEXT_P(GET_TEXT("OK"));
+	PG_RETURN_TEXT_P(cstring_to_text("OK"));
 }
 
 /*
@@ -290,7 +288,7 @@ dblink_disconnect(PG_FUNCTION_ARGS)
 
 	if (PG_NARGS() == 1)
 	{
-		conname = GET_STR(PG_GETARG_TEXT_P(0));
+		conname = text_to_cstring(PG_GETARG_TEXT_PP(0));
 		rconn = getConnectionByName(conname);
 		if (rconn)
 			conn = rconn->conn;
@@ -310,7 +308,7 @@ dblink_disconnect(PG_FUNCTION_ARGS)
 	else
 		pconn->conn = NULL;
 
-	PG_RETURN_TEXT_P(GET_TEXT("OK"));
+	PG_RETURN_TEXT_P(cstring_to_text("OK"));
 }
 
 /*
@@ -336,8 +334,8 @@ dblink_open(PG_FUNCTION_ARGS)
 	if (PG_NARGS() == 2)
 	{
 		/* text,text */
-		curname = GET_STR(PG_GETARG_TEXT_P(0));
-		sql = GET_STR(PG_GETARG_TEXT_P(1));
+		curname = text_to_cstring(PG_GETARG_TEXT_PP(0));
+		sql = text_to_cstring(PG_GETARG_TEXT_PP(1));
 		rconn = pconn;
 	}
 	else if (PG_NARGS() == 3)
@@ -345,25 +343,25 @@ dblink_open(PG_FUNCTION_ARGS)
 		/* might be text,text,text or text,text,bool */
 		if (get_fn_expr_argtype(fcinfo->flinfo, 2) == BOOLOID)
 		{
-			curname = GET_STR(PG_GETARG_TEXT_P(0));
-			sql = GET_STR(PG_GETARG_TEXT_P(1));
+			curname = text_to_cstring(PG_GETARG_TEXT_PP(0));
+			sql = text_to_cstring(PG_GETARG_TEXT_PP(1));
 			fail = PG_GETARG_BOOL(2);
 			rconn = pconn;
 		}
 		else
 		{
-			conname = GET_STR(PG_GETARG_TEXT_P(0));
-			curname = GET_STR(PG_GETARG_TEXT_P(1));
-			sql = GET_STR(PG_GETARG_TEXT_P(2));
+			conname = text_to_cstring(PG_GETARG_TEXT_PP(0));
+			curname = text_to_cstring(PG_GETARG_TEXT_PP(1));
+			sql = text_to_cstring(PG_GETARG_TEXT_PP(2));
 			rconn = getConnectionByName(conname);
 		}
 	}
 	else if (PG_NARGS() == 4)
 	{
 		/* text,text,text,bool */
-		conname = GET_STR(PG_GETARG_TEXT_P(0));
-		curname = GET_STR(PG_GETARG_TEXT_P(1));
-		sql = GET_STR(PG_GETARG_TEXT_P(2));
+		conname = text_to_cstring(PG_GETARG_TEXT_PP(0));
+		curname = text_to_cstring(PG_GETARG_TEXT_PP(1));
+		sql = text_to_cstring(PG_GETARG_TEXT_PP(2));
 		fail = PG_GETARG_BOOL(3);
 		rconn = getConnectionByName(conname);
 	}
@@ -403,12 +401,12 @@ dblink_open(PG_FUNCTION_ARGS)
 		else
 		{
 			DBLINK_RES_ERROR_AS_NOTICE("sql error");
-			PG_RETURN_TEXT_P(GET_TEXT("ERROR"));
+			PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
 		}
 	}
 
 	PQclear(res);
-	PG_RETURN_TEXT_P(GET_TEXT("OK"));
+	PG_RETURN_TEXT_P(cstring_to_text("OK"));
 }
 
 /*
@@ -433,7 +431,7 @@ dblink_close(PG_FUNCTION_ARGS)
 	if (PG_NARGS() == 1)
 	{
 		/* text */
-		curname = GET_STR(PG_GETARG_TEXT_P(0));
+		curname = text_to_cstring(PG_GETARG_TEXT_PP(0));
 		rconn = pconn;
 	}
 	else if (PG_NARGS() == 2)
@@ -441,22 +439,22 @@ dblink_close(PG_FUNCTION_ARGS)
 		/* might be text,text or text,bool */
 		if (get_fn_expr_argtype(fcinfo->flinfo, 1) == BOOLOID)
 		{
-			curname = GET_STR(PG_GETARG_TEXT_P(0));
+			curname = text_to_cstring(PG_GETARG_TEXT_PP(0));
 			fail = PG_GETARG_BOOL(1);
 			rconn = pconn;
 		}
 		else
 		{
-			conname = GET_STR(PG_GETARG_TEXT_P(0));
-			curname = GET_STR(PG_GETARG_TEXT_P(1));
+			conname = text_to_cstring(PG_GETARG_TEXT_PP(0));
+			curname = text_to_cstring(PG_GETARG_TEXT_PP(1));
 			rconn = getConnectionByName(conname);
 		}
 	}
 	if (PG_NARGS() == 3)
 	{
 		/* text,text,bool */
-		conname = GET_STR(PG_GETARG_TEXT_P(0));
-		curname = GET_STR(PG_GETARG_TEXT_P(1));
+		conname = text_to_cstring(PG_GETARG_TEXT_PP(0));
+		curname = text_to_cstring(PG_GETARG_TEXT_PP(1));
 		fail = PG_GETARG_BOOL(2);
 		rconn = getConnectionByName(conname);
 	}
@@ -477,7 +475,7 @@ dblink_close(PG_FUNCTION_ARGS)
 		else
 		{
 			DBLINK_RES_ERROR_AS_NOTICE("sql error");
-			PG_RETURN_TEXT_P(GET_TEXT("ERROR"));
+			PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
 		}
 	}
 
@@ -500,7 +498,7 @@ dblink_close(PG_FUNCTION_ARGS)
 		}
 	}
 
-	PG_RETURN_TEXT_P(GET_TEXT("OK"));
+	PG_RETURN_TEXT_P(cstring_to_text("OK"));
 }
 
 /*
@@ -535,8 +533,8 @@ dblink_fetch(PG_FUNCTION_ARGS)
 		if (PG_NARGS() == 4)
 		{
 			/* text,text,int,bool */
-			conname = GET_STR(PG_GETARG_TEXT_P(0));
-			curname = GET_STR(PG_GETARG_TEXT_P(1));
+			conname = text_to_cstring(PG_GETARG_TEXT_PP(0));
+			curname = text_to_cstring(PG_GETARG_TEXT_PP(1));
 			howmany = PG_GETARG_INT32(2);
 			fail = PG_GETARG_BOOL(3);
 
@@ -549,15 +547,15 @@ dblink_fetch(PG_FUNCTION_ARGS)
 			/* text,text,int or text,int,bool */
 			if (get_fn_expr_argtype(fcinfo->flinfo, 2) == BOOLOID)
 			{
-				curname = GET_STR(PG_GETARG_TEXT_P(0));
+				curname = text_to_cstring(PG_GETARG_TEXT_PP(0));
 				howmany = PG_GETARG_INT32(1);
 				fail = PG_GETARG_BOOL(2);
 				conn = pconn->conn;
 			}
 			else
 			{
-				conname = GET_STR(PG_GETARG_TEXT_P(0));
-				curname = GET_STR(PG_GETARG_TEXT_P(1));
+				conname = text_to_cstring(PG_GETARG_TEXT_PP(0));
+				curname = text_to_cstring(PG_GETARG_TEXT_PP(1));
 				howmany = PG_GETARG_INT32(2);
 
 				rconn = getConnectionByName(conname);
@@ -568,7 +566,7 @@ dblink_fetch(PG_FUNCTION_ARGS)
 		else if (PG_NARGS() == 2)
 		{
 			/* text,int */
-			curname = GET_STR(PG_GETARG_TEXT_P(0));
+			curname = text_to_cstring(PG_GETARG_TEXT_PP(0));
 			howmany = PG_GETARG_INT32(1);
 			conn = pconn->conn;
 		}
@@ -769,7 +767,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
 			{
 				/* text,text,bool */
 				DBLINK_GET_CONN;
-				sql = GET_STR(PG_GETARG_TEXT_P(1));
+				sql = text_to_cstring(PG_GETARG_TEXT_PP(1));
 				fail = PG_GETARG_BOOL(2);
 			}
 			else if (PG_NARGS() == 2)
@@ -778,20 +776,20 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
 				if (get_fn_expr_argtype(fcinfo->flinfo, 1) == BOOLOID)
 				{
 					conn = pconn->conn;
-					sql = GET_STR(PG_GETARG_TEXT_P(0));
+					sql = text_to_cstring(PG_GETARG_TEXT_PP(0));
 					fail = PG_GETARG_BOOL(1);
 				}
 				else
 				{
 					DBLINK_GET_CONN;
-					sql = GET_STR(PG_GETARG_TEXT_P(1));
+					sql = text_to_cstring(PG_GETARG_TEXT_PP(1));
 				}
 			}
 			else if (PG_NARGS() == 1)
 			{
 				/* text */
 				conn = pconn->conn;
-				sql = GET_STR(PG_GETARG_TEXT_P(0));
+				sql = text_to_cstring(PG_GETARG_TEXT_PP(0));
 			}
 			else
 				/* shouldn't happen */
@@ -821,7 +819,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
 			if (PG_NARGS() == 2)
 			{
 				DBLINK_GET_CONN;
-				sql = GET_STR(PG_GETARG_TEXT_P(1));
+				sql = text_to_cstring(PG_GETARG_TEXT_PP(1));
 			}
 			else
 				/* shouldn't happen */
@@ -1024,7 +1022,7 @@ dblink_get_connections(PG_FUNCTION_ARGS)
 		{
 			/* stash away current value */
 			astate = accumArrayResult(astate,
-									  PointerGetDatum(GET_TEXT(hentry->name)),
+									  CStringGetTextDatum(hentry->name),
 									  false, TEXTOID, CurrentMemoryContext);
 		}
 	}
@@ -1087,9 +1085,9 @@ dblink_cancel_query(PG_FUNCTION_ARGS)
 	PQfreeCancel(cancel);
 
 	if (res == 1)
-		PG_RETURN_TEXT_P(GET_TEXT("OK"));
+		PG_RETURN_TEXT_P(cstring_to_text("OK"));
 	else
-		PG_RETURN_TEXT_P(GET_TEXT(errbuf));
+		PG_RETURN_TEXT_P(cstring_to_text(errbuf));
 }
 
 
@@ -1116,9 +1114,9 @@ dblink_error_message(PG_FUNCTION_ARGS)
 
 	msg = PQerrorMessage(conn);
 	if (msg == NULL || msg[0] == '\0')
-		PG_RETURN_TEXT_P(GET_TEXT("OK"));
+		PG_RETURN_TEXT_P(cstring_to_text("OK"));
 	else
-		PG_RETURN_TEXT_P(GET_TEXT(msg));
+		PG_RETURN_TEXT_P(cstring_to_text(msg));
 }
 
 /*
@@ -1146,7 +1144,7 @@ dblink_exec(PG_FUNCTION_ARGS)
 	{
 		/* must be text,text,bool */
 		DBLINK_GET_CONN;
-		sql = GET_STR(PG_GETARG_TEXT_P(1));
+		sql = text_to_cstring(PG_GETARG_TEXT_PP(1));
 		fail = PG_GETARG_BOOL(2);
 	}
 	else if (PG_NARGS() == 2)
@@ -1155,20 +1153,20 @@ dblink_exec(PG_FUNCTION_ARGS)
 		if (get_fn_expr_argtype(fcinfo->flinfo, 1) == BOOLOID)
 		{
 			conn = pconn->conn;
-			sql = GET_STR(PG_GETARG_TEXT_P(0));
+			sql = text_to_cstring(PG_GETARG_TEXT_PP(0));
 			fail = PG_GETARG_BOOL(1);
 		}
 		else
 		{
 			DBLINK_GET_CONN;
-			sql = GET_STR(PG_GETARG_TEXT_P(1));
+			sql = text_to_cstring(PG_GETARG_TEXT_PP(1));
 		}
 	}
 	else if (PG_NARGS() == 1)
 	{
 		/* must be single text argument */
 		conn = pconn->conn;
-		sql = GET_STR(PG_GETARG_TEXT_P(0));
+		sql = text_to_cstring(PG_GETARG_TEXT_PP(0));
 	}
 	else
 		/* shouldn't happen */
@@ -1196,7 +1194,7 @@ dblink_exec(PG_FUNCTION_ARGS)
 		 * and save a copy of the command status string to return as our
 		 * result tuple
 		 */
-		sql_cmd_status = GET_TEXT("ERROR");
+		sql_cmd_status = cstring_to_text("ERROR");
 
 	}
 	else if (PQresultStatus(res) == PGRES_COMMAND_OK)
@@ -1210,7 +1208,7 @@ dblink_exec(PG_FUNCTION_ARGS)
 		 * and save a copy of the command status string to return as our
 		 * result tuple
 		 */
-		sql_cmd_status = GET_TEXT(PQcmdStatus(res));
+		sql_cmd_status = cstring_to_text(PQcmdStatus(res));
 		PQclear(res);
 	}
 	else
@@ -1267,7 +1265,7 @@ dblink_get_pkey(PG_FUNCTION_ARGS)
 			ereport(ERROR,
 					(errcode(ERRCODE_UNDEFINED_TABLE),
 					 errmsg("relation \"%s\" does not exist",
-							GET_STR(PG_GETARG_TEXT_P(0)))));
+							text_to_cstring(PG_GETARG_TEXT_PP(0)))));
 
 		/*
 		 * need a tuple descriptor representing one INT and one TEXT column
@@ -1387,7 +1385,7 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_TABLE),
 				 errmsg("relation \"%s\" does not exist",
-						GET_STR(relname_text))));
+						text_to_cstring(relname_text))));
 
 	/*
 	 * There should be at least one key attribute
@@ -1443,7 +1441,7 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
 	/*
 	 * And send it
 	 */
-	PG_RETURN_TEXT_P(GET_TEXT(sql));
+	PG_RETURN_TEXT_P(cstring_to_text(sql));
 }
 
 
@@ -1484,7 +1482,7 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_TABLE),
 				 errmsg("relation \"%s\" does not exist",
-						GET_STR(relname_text))));
+						text_to_cstring(relname_text))));
 
 	/*
 	 * There should be at least one key attribute
@@ -1525,7 +1523,7 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
 	/*
 	 * And send it
 	 */
-	PG_RETURN_TEXT_P(GET_TEXT(sql));
+	PG_RETURN_TEXT_P(cstring_to_text(sql));
 }
 
 
@@ -1573,7 +1571,7 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_TABLE),
 				 errmsg("relation \"%s\" does not exist",
-						GET_STR(relname_text))));
+						text_to_cstring(relname_text))));
 
 	/*
 	 * There should be one source array key values for each key attnum
@@ -1629,7 +1627,7 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
 	/*
 	 * And send it
 	 */
-	PG_RETURN_TEXT_P(GET_TEXT(sql));
+	PG_RETURN_TEXT_P(cstring_to_text(sql));
 }
 
 /*
@@ -1643,7 +1641,7 @@ Datum
 dblink_current_query(PG_FUNCTION_ARGS)
 {
 	if (debug_query_string)
-		PG_RETURN_TEXT_P(GET_TEXT(debug_query_string));
+		PG_RETURN_TEXT_P(cstring_to_text(debug_query_string));
 	else
 		PG_RETURN_NULL();
 }
@@ -1763,8 +1761,7 @@ get_text_array_contents(ArrayType *array, int *numitems)
 		}
 		else
 		{
-			values[i] = DatumGetCString(DirectFunctionCall1(textout,
-													  PointerGetDatum(ptr)));
+			values[i] = TextDatumGetCString(PointerGetDatum(ptr));
 			ptr = att_addlength_pointer(ptr, typlen, ptr);
 			ptr = (char *) att_align_nominal(ptr, typalign);
 		}
@@ -2026,9 +2023,10 @@ quote_literal_cstr(char *rawstr)
 	text	   *result_text;
 	char	   *result;
 
-	rawstr_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(rawstr)));
-	result_text = DatumGetTextP(DirectFunctionCall1(quote_literal, PointerGetDatum(rawstr_text)));
-	result = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(result_text)));
+	rawstr_text = cstring_to_text(rawstr);
+	result_text = DatumGetTextP(DirectFunctionCall1(quote_literal,
+													PointerGetDatum(rawstr_text)));
+	result = text_to_cstring(result_text);
 
 	return result;
 }
@@ -2044,9 +2042,10 @@ quote_ident_cstr(char *rawstr)
 	text	   *result_text;
 	char	   *result;
 
-	rawstr_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(rawstr)));
-	result_text = DatumGetTextP(DirectFunctionCall1(quote_ident, PointerGetDatum(rawstr_text)));
-	result = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(result_text)));
+	rawstr_text = cstring_to_text(rawstr);
+	result_text = DatumGetTextP(DirectFunctionCall1(quote_ident,
+													PointerGetDatum(rawstr_text)));
+	result = text_to_cstring(result_text);
 
 	return result;
 }
diff --git a/contrib/fuzzystrmatch/dmetaphone.c b/contrib/fuzzystrmatch/dmetaphone.c
index acd9d0c62925307e0547a899684b2eb4940cac88..5bb07640bf61cd876d3db7b2cd8eddfc2ce46157 100644
--- a/contrib/fuzzystrmatch/dmetaphone.c
+++ b/contrib/fuzzystrmatch/dmetaphone.c
@@ -1,7 +1,7 @@
 /*
  * This is a port of the Double Metaphone algorithm for use in PostgreSQL.
  *
- * $PostgreSQL: pgsql/contrib/fuzzystrmatch/dmetaphone.c,v 1.11 2007/02/27 23:48:05 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/fuzzystrmatch/dmetaphone.c,v 1.12 2008/03/25 22:42:41 tgl Exp $
  *
  * Double Metaphone computes 2 "sounds like" strings - a primary and an
  * alternate. In most cases they are the same, but for foreign names
@@ -101,7 +101,7 @@ The remaining code is authored by Andrew Dunstan <amdunstan@ncshp.org> and
 
 #include "postgres.h"
 
-#include "fmgr.h"
+#include "utils/builtins.h"
 
 /* turn off assertions for embedded function */
 #define NDEBUG
@@ -118,14 +118,12 @@ extern Datum dmetaphone(PG_FUNCTION_ARGS);
 extern Datum dmetaphone_alt(PG_FUNCTION_ARGS);
 
 /* prototype for the main function we got from the perl module */
-static void
-			DoubleMetaphone(char *, char **);
+static void DoubleMetaphone(char *, char **);
 
 #ifndef DMETAPHONE_MAIN
 
 /*
  * The PostgreSQL visible dmetaphone function.
- *
  */
 
 PG_FUNCTION_INFO_V1(dmetaphone);
@@ -133,47 +131,28 @@ PG_FUNCTION_INFO_V1(dmetaphone);
 Datum
 dmetaphone(PG_FUNCTION_ARGS)
 {
-	text	   *arg,
-			   *result;
-	int			alen,
-				rsize;
+	text	   *arg;
 	char	   *aptr,
 			   *codes[2],
-			   *code,
-			   *rptr;
+			   *code;
 
 #ifdef DMETAPHONE_NOSTRICT
 	if (PG_ARGISNULL(0))
-		PG_RETURNNULL();
+		PG_RETURN_NULL();
 #endif
 	arg = PG_GETARG_TEXT_P(0);
-	alen = VARSIZE(arg) - VARHDRSZ;
-
-	/*
-	 * Postgres' string values might not have trailing nuls. The VARSIZE will
-	 * not include the nul in any case so we copy things out and add a
-	 * trailing nul. When we copy back we ignore the nul (and we don't make
-	 * space for it).
-	 */
-
-	aptr = palloc(alen + 1);
-	memcpy(aptr, VARDATA(arg), alen);
-	aptr[alen] = 0;
+	aptr = text_to_cstring(arg);
+
 	DoubleMetaphone(aptr, codes);
 	code = codes[0];
 	if (!code)
 		code = "";
-	rsize = VARHDRSZ + strlen(code);
-	result = (text *) palloc(rsize);
-	rptr = VARDATA(result);
-	memcpy(rptr, code, rsize - VARHDRSZ);
-	SET_VARSIZE(result, rsize);
-	PG_RETURN_TEXT_P(result);
+
+	PG_RETURN_TEXT_P(cstring_to_text(code));
 }
 
 /*
  * The PostgreSQL visible dmetaphone_alt function.
- *
  */
 
 PG_FUNCTION_INFO_V1(dmetaphone_alt);
@@ -181,34 +160,24 @@ PG_FUNCTION_INFO_V1(dmetaphone_alt);
 Datum
 dmetaphone_alt(PG_FUNCTION_ARGS)
 {
-	text	   *arg,
-			   *result;
-	int			alen,
-				rsize;
+	text	   *arg;
 	char	   *aptr,
 			   *codes[2],
-			   *code,
-			   *rptr;
+			   *code;
 
 #ifdef DMETAPHONE_NOSTRICT
 	if (PG_ARGISNULL(0))
-		PG_RETURNNULL();
+		PG_RETURN_NULL();
 #endif
 	arg = PG_GETARG_TEXT_P(0);
-	alen = VARSIZE(arg) - VARHDRSZ;
-	aptr = palloc(alen + 1);
-	memcpy(aptr, VARDATA(arg), alen);
-	aptr[alen] = 0;
+	aptr = text_to_cstring(arg);
+
 	DoubleMetaphone(aptr, codes);
 	code = codes[1];
 	if (!code)
 		code = "";
-	rsize = VARHDRSZ + strlen(code);
-	result = (text *) palloc(rsize);
-	rptr = VARDATA(result);
-	memcpy(rptr, code, rsize - VARHDRSZ);
-	SET_VARSIZE(result, rsize);
-	PG_RETURN_TEXT_P(result);
+
+	PG_RETURN_TEXT_P(cstring_to_text(code));
 }
 
 
diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.c b/contrib/fuzzystrmatch/fuzzystrmatch.c
index 9f0898b42747dc6f37601476110638340d3f97ed..7a6aae039fea5ee0dc095c65f02dda8fb0add39a 100644
--- a/contrib/fuzzystrmatch/fuzzystrmatch.c
+++ b/contrib/fuzzystrmatch/fuzzystrmatch.c
@@ -5,7 +5,7 @@
  *
  * Joe Conway <mail@joeconway.com>
  *
- * $PostgreSQL: pgsql/contrib/fuzzystrmatch/fuzzystrmatch.c,v 1.25 2008/01/01 19:45:45 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/fuzzystrmatch/fuzzystrmatch.c,v 1.26 2008/03/25 22:42:41 tgl Exp $
  * Copyright (c) 2001-2008, PostgreSQL Global Development Group
  * ALL RIGHTS RESERVED;
  *
@@ -56,11 +56,11 @@ PG_FUNCTION_INFO_V1(levenshtein);
 Datum
 levenshtein(PG_FUNCTION_ARGS)
 {
-	char	   *str_s;
+	char	   *str_s = TextDatumGetCString(PG_GETARG_DATUM(0));
+	char	   *str_t = TextDatumGetCString(PG_GETARG_DATUM(1));
+	int			cols = strlen(str_s) + 1;
+	int			rows = strlen(str_t) + 1;
 	char	   *str_s0;
-	char	   *str_t;
-	int			cols = 0;
-	int			rows = 0;
 	int		   *u_cells;
 	int		   *l_cells;
 	int		   *tmp;
@@ -68,16 +68,10 @@ levenshtein(PG_FUNCTION_ARGS)
 	int			j;
 
 	/*
-	 * Fetch the arguments. str_s is referred to as the "source" cols = length
-	 * of source + 1 to allow for the initialization column str_t is referred
-	 * to as the "target", rows = length of target + 1 rows = length of target
-	 * + 1 to allow for the initialization row
+	 * str_s is referred to as the "source", str_t is referred to as the
+	 * "target", cols = length of source + 1 to allow for the initialization
+	 * column, rows = length of target + 1 to allow for the initialization row
 	 */
-	str_s = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0))));
-	str_t = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(1))));
-
-	cols = strlen(str_s) + 1;
-	rows = strlen(str_t) + 1;
 
 	/*
 	 * Restrict the length of the strings being compared to something
@@ -201,25 +195,19 @@ levenshtein(PG_FUNCTION_ARGS)
  * Returns number of characters requested
  * (suggested value is 4)
  */
-#define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))
-
 PG_FUNCTION_INFO_V1(metaphone);
 Datum
 metaphone(PG_FUNCTION_ARGS)
 {
+	char	   *str_i = TextDatumGetCString(PG_GETARG_DATUM(0));
+	size_t		str_i_len = strlen(str_i);
 	int			reqlen;
-	char	   *str_i;
-	size_t		str_i_len;
 	char	   *metaph;
-	text	   *result_text;
 	int			retval;
 
-	str_i = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0))));
-	str_i_len = strlen(str_i);
-
 	/* return an empty string if we receive one */
 	if (!(str_i_len > 0))
-		PG_RETURN_TEXT_P(GET_TEXT(""));
+		PG_RETURN_TEXT_P(cstring_to_text(""));
 
 	if (str_i_len > MAX_METAPHONE_STRLEN)
 		ereport(ERROR,
@@ -247,18 +235,12 @@ metaphone(PG_FUNCTION_ARGS)
 
 	retval = _metaphone(str_i, reqlen, &metaph);
 	if (retval == META_SUCCESS)
-	{
-		result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(metaph)));
-		PG_RETURN_TEXT_P(result_text);
-	}
+		PG_RETURN_TEXT_P(cstring_to_text(metaph));
 	else
 	{
 		/* internal error */
 		elog(ERROR, "metaphone: failure");
-
-		/*
-		 * Keep the compiler quiet
-		 */
+		/* keep the compiler quiet */
 		PG_RETURN_NULL();
 	}
 }
@@ -695,11 +677,11 @@ soundex(PG_FUNCTION_ARGS)
 	char		outstr[SOUNDEX_LEN + 1];
 	char	   *arg;
 
-	arg = _textout(PG_GETARG_TEXT_P(0));
+	arg = text_to_cstring(PG_GETARG_TEXT_P(0));
 
 	_soundex(arg, outstr);
 
-	PG_RETURN_TEXT_P(_textin(outstr));
+	PG_RETURN_TEXT_P(cstring_to_text(outstr));
 }
 
 static void
@@ -761,8 +743,8 @@ difference(PG_FUNCTION_ARGS)
 	int			i,
 				result;
 
-	_soundex(_textout(PG_GETARG_TEXT_P(0)), sndx1);
-	_soundex(_textout(PG_GETARG_TEXT_P(1)), sndx2);
+	_soundex(text_to_cstring(PG_GETARG_TEXT_P(0)), sndx1);
+	_soundex(text_to_cstring(PG_GETARG_TEXT_P(1)), sndx2);
 
 	result = 0;
 	for (i = 0; i < SOUNDEX_LEN; i++)
diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.h b/contrib/fuzzystrmatch/fuzzystrmatch.h
index 73a88207ee5474ec87886a217620bf0fa4bdc56e..22670ba948385ffafa5ed9faa9c7d2226289d5f4 100644
--- a/contrib/fuzzystrmatch/fuzzystrmatch.h
+++ b/contrib/fuzzystrmatch/fuzzystrmatch.h
@@ -5,7 +5,7 @@
  *
  * Joe Conway <mail@joeconway.com>
  *
- * $PostgreSQL: pgsql/contrib/fuzzystrmatch/fuzzystrmatch.h,v 1.16 2008/01/01 19:45:45 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/fuzzystrmatch/fuzzystrmatch.h,v 1.17 2008/03/25 22:42:41 tgl Exp $
  * Copyright (c) 2001-2008, PostgreSQL Global Development Group
  * ALL RIGHTS RESERVED;
  *
@@ -69,8 +69,6 @@ extern Datum difference(PG_FUNCTION_ARGS);
 static void _soundex(const char *instr, char *outstr);
 
 #define SOUNDEX_LEN 4
-#define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str))
-#define _textout(str) DatumGetPointer(DirectFunctionCall1(textout, PointerGetDatum(str)))
 
 /*									ABCDEFGHIJKLMNOPQRSTUVWXYZ */
 static const char *soundex_table = "01230120022455012623010202";
diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c
index bcac30ee6fdd3c4720c862eaf5ac9dade3619e2e..961abfe35c968a110527352b58f1d341e11e8e30 100644
--- a/contrib/hstore/hstore_op.c
+++ b/contrib/hstore/hstore_op.c
@@ -52,13 +52,12 @@ fetchval(PG_FUNCTION_ARGS)
 		PG_RETURN_NULL();
 	}
 
-	out = palloc(VARHDRSZ + entry->vallen);
-	memcpy(VARDATA(out), STRPTR(hs) + entry->pos + entry->keylen, entry->vallen);
-	SET_VARSIZE(out, VARHDRSZ + entry->vallen);
+	out = cstring_to_text_with_len(STRPTR(hs) + entry->pos + entry->keylen,
+								   entry->vallen);
 
 	PG_FREE_IF_COPY(hs, 0);
 	PG_FREE_IF_COPY(key, 1);
-	PG_RETURN_POINTER(out);
+	PG_RETURN_TEXT_P(out);
 }
 
 PG_FUNCTION_INFO_V1(exists);
@@ -330,22 +329,19 @@ akeys(PG_FUNCTION_ARGS)
 	d = (Datum *) palloc(sizeof(Datum) * (hs->size + 1));
 	while (ptr - ARRPTR(hs) < hs->size)
 	{
-		text	   *item = (text *) palloc(VARHDRSZ + ptr->keylen);
+		text	   *item;
 
-		SET_VARSIZE(item, VARHDRSZ + ptr->keylen);
-		memcpy(VARDATA(item), base + ptr->pos, ptr->keylen);
+		item = cstring_to_text_with_len(base + ptr->pos, ptr->keylen);
 		d[ptr - ARRPTR(hs)] = PointerGetDatum(item);
 		ptr++;
 	}
 
-	a = construct_array(
-						d,
+	a = construct_array(d,
 						hs->size,
 						TEXTOID,
 						-1,
 						false,
-						'i'
-		);
+						'i');
 
 	ptr = ARRPTR(hs);
 	while (ptr - ARRPTR(hs) < hs->size)
@@ -374,23 +370,20 @@ avals(PG_FUNCTION_ARGS)
 	d = (Datum *) palloc(sizeof(Datum) * (hs->size + 1));
 	while (ptr - ARRPTR(hs) < hs->size)
 	{
-		int			vallen = (ptr->valisnull) ? 0 : ptr->vallen;
-		text	   *item = (text *) palloc(VARHDRSZ + vallen);
+		text	   *item;
 
-		SET_VARSIZE(item, VARHDRSZ + vallen);
-		memcpy(VARDATA(item), base + ptr->pos + ptr->keylen, vallen);
+		item = cstring_to_text_with_len(base + ptr->pos + ptr->keylen,
+										(ptr->valisnull) ? 0 : ptr->vallen);
 		d[ptr - ARRPTR(hs)] = PointerGetDatum(item);
 		ptr++;
 	}
 
-	a = construct_array(
-						d,
+	a = construct_array(d,
 						hs->size,
 						TEXTOID,
 						-1,
 						false,
-						'i'
-		);
+						'i');
 
 	ptr = ARRPTR(hs);
 	while (ptr - ARRPTR(hs) < hs->size)
@@ -451,10 +444,10 @@ skeys(PG_FUNCTION_ARGS)
 	if (st->i < st->hs->size)
 	{
 		HEntry	   *ptr = &(ARRPTR(st->hs)[st->i]);
-		text	   *item = (text *) palloc(VARHDRSZ + ptr->keylen);
+		text	   *item;
 
-		SET_VARSIZE(item, VARHDRSZ + ptr->keylen);
-		memcpy(VARDATA(item), STRPTR(st->hs) + ptr->pos, ptr->keylen);
+		item = cstring_to_text_with_len(STRPTR(st->hs) + ptr->pos,
+										ptr->keylen);
 		st->i++;
 
 		SRF_RETURN_NEXT(funcctx, PointerGetDatum(item));
@@ -502,11 +495,10 @@ svals(PG_FUNCTION_ARGS)
 		}
 		else
 		{
-			int			vallen = ptr->vallen;
-			text	   *item = (text *) palloc(VARHDRSZ + vallen);
+			text	   *item;
 
-			SET_VARSIZE(item, VARHDRSZ + vallen);
-			memcpy(VARDATA(item), STRPTR(st->hs) + ptr->pos + ptr->keylen, vallen);
+			item = cstring_to_text_with_len(STRPTR(st->hs) + ptr->pos + ptr->keylen,
+											ptr->vallen);
 			st->i++;
 
 			SRF_RETURN_NEXT(funcctx, PointerGetDatum(item));
@@ -617,9 +609,7 @@ each(PG_FUNCTION_ARGS)
 		text	   *item;
 		HeapTuple	tuple;
 
-		item = (text *) palloc(VARHDRSZ + ptr->keylen);
-		SET_VARSIZE(item, VARHDRSZ + ptr->keylen);
-		memcpy(VARDATA(item), STRPTR(st->hs) + ptr->pos, ptr->keylen);
+		item = cstring_to_text_with_len(STRPTR(st->hs) + ptr->pos, ptr->keylen);
 		dvalues[0] = PointerGetDatum(item);
 
 		if (ptr->valisnull)
@@ -629,11 +619,8 @@ each(PG_FUNCTION_ARGS)
 		}
 		else
 		{
-			int			vallen = ptr->vallen;
-
-			item = (text *) palloc(VARHDRSZ + vallen);
-			SET_VARSIZE(item, VARHDRSZ + vallen);
-			memcpy(VARDATA(item), STRPTR(st->hs) + ptr->pos + ptr->keylen, vallen);
+			item = cstring_to_text_with_len(STRPTR(st->hs) + ptr->pos + ptr->keylen,
+											ptr->vallen);
 			dvalues[1] = PointerGetDatum(item);
 		}
 		st->i++;
diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
index 2344d0b50be110fcec542875332380dffcb79fae..ef9430901dc48718ecd35c5acad7452d5fcf3c6d 100644
--- a/contrib/intarray/_int_bool.c
+++ b/contrib/intarray/_int_bool.c
@@ -765,9 +765,7 @@ querytree(PG_FUNCTION_ARGS)
 
 	if (len == 0)
 	{
-		res = (text *) palloc(1 + VARHDRSZ);
-		SET_VARSIZE(res, 1 + VARHDRSZ);
-		*((char *) VARDATA(res)) = 'T';
+		res = cstring_to_text("T");
 	}
 	else
 	{
@@ -776,12 +774,9 @@ querytree(PG_FUNCTION_ARGS)
 		nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
 		*(nrm.cur) = '\0';
 		infix(&nrm, true);
-
-		res = (text *) palloc(nrm.cur - nrm.buf + VARHDRSZ);
-		SET_VARSIZE(res, nrm.cur - nrm.buf + VARHDRSZ);
-		memcpy(VARDATA(res), nrm.buf, nrm.cur - nrm.buf);
+		res = cstring_to_text_with_len(nrm.buf, nrm.cur - nrm.buf);
 	}
 	pfree(q);
 
-	PG_RETURN_POINTER(res);
+	PG_RETURN_TEXT_P(res);
 }
diff --git a/contrib/ltree/ltree_op.c b/contrib/ltree/ltree_op.c
index 3eb854fbdc916925ce9d9e68a08e2c40814db722..5a789865d8f7af928e7db4720a8c26de7f6d223c 100644
--- a/contrib/ltree/ltree_op.c
+++ b/contrib/ltree/ltree_op.c
@@ -1,7 +1,7 @@
 /*
  * op function for ltree
  * Teodor Sigaev <teodor@stack.net>
- * $PostgreSQL: pgsql/contrib/ltree/ltree_op.c,v 1.17 2008/03/09 00:32:09 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/ltree/ltree_op.c,v 1.18 2008/03/25 22:42:41 tgl Exp $
  */
 
 #include "ltree.h"
@@ -314,19 +314,15 @@ Datum
 ltree_addtext(PG_FUNCTION_ARGS)
 {
 	ltree	   *a = PG_GETARG_LTREE(0);
-	text	   *b = PG_GETARG_TEXT_P(1);
+	text	   *b = PG_GETARG_TEXT_PP(1);
 	char	   *s;
 	ltree	   *r,
 			   *tmp;
 
-	s = (char *) palloc(VARSIZE(b) - VARHDRSZ + 1);
-	memcpy(s, VARDATA(b), VARSIZE(b) - VARHDRSZ);
-	s[VARSIZE(b) - VARHDRSZ] = '\0';
+	s = text_to_cstring(b);
 
-	tmp = (ltree *) DatumGetPointer(DirectFunctionCall1(
-														ltree_in,
-														PointerGetDatum(s)
-														));
+	tmp = (ltree *) DatumGetPointer(DirectFunctionCall1(ltree_in,
+														PointerGetDatum(s)));
 
 	pfree(s);
 
@@ -403,19 +399,15 @@ Datum
 ltree_textadd(PG_FUNCTION_ARGS)
 {
 	ltree	   *a = PG_GETARG_LTREE(1);
-	text	   *b = PG_GETARG_TEXT_P(0);
+	text	   *b = PG_GETARG_TEXT_PP(0);
 	char	   *s;
 	ltree	   *r,
 			   *tmp;
 
-	s = (char *) palloc(VARSIZE(b) - VARHDRSZ + 1);
-	memcpy(s, VARDATA(b), VARSIZE(b) - VARHDRSZ);
-	s[VARSIZE(b) - VARHDRSZ] = '\0';
+	s = text_to_cstring(b);
 
-	tmp = (ltree *) DatumGetPointer(DirectFunctionCall1(
-														ltree_in,
-														PointerGetDatum(s)
-														));
+	tmp = (ltree *) DatumGetPointer(DirectFunctionCall1(ltree_in,
+														PointerGetDatum(s)));
 
 	pfree(s);
 
@@ -517,17 +509,14 @@ lca(PG_FUNCTION_ARGS)
 Datum
 text2ltree(PG_FUNCTION_ARGS)
 {
-	text	   *in = PG_GETARG_TEXT_P(0);
-	char	   *s = (char *) palloc(VARSIZE(in) - VARHDRSZ + 1);
+	text	   *in = PG_GETARG_TEXT_PP(0);
+	char	   *s;
 	ltree	   *out;
 
-	memcpy(s, VARDATA(in), VARSIZE(in) - VARHDRSZ);
-	s[VARSIZE(in) - VARHDRSZ] = '\0';
+	s = text_to_cstring(in);
 
-	out = (ltree *) DatumGetPointer(DirectFunctionCall1(
-														ltree_in,
-														PointerGetDatum(s)
-														));
+	out = (ltree *) DatumGetPointer(DirectFunctionCall1(ltree_in,
+														PointerGetDatum(s)));
 	pfree(s);
 	PG_FREE_IF_COPY(in, 0);
 	PG_RETURN_POINTER(out);
diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c
index 3b82389729be7c9fe47df244169127fb1d835496..704161c716ddea82399b42cf3366dd11c51ee7e9 100644
--- a/contrib/pageinspect/heapfuncs.c
+++ b/contrib/pageinspect/heapfuncs.c
@@ -18,7 +18,7 @@
  * Copyright (c) 2007-2008, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/contrib/pageinspect/heapfuncs.c,v 1.4 2008/01/01 20:31:21 tgl Exp $
+ *	  $PostgreSQL: pgsql/contrib/pageinspect/heapfuncs.c,v 1.5 2008/03/25 22:42:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,8 +36,6 @@
 
 Datum		heap_page_items(PG_FUNCTION_ARGS);
 
-#define GET_TEXT(str_) \
-		DirectFunctionCall1(textin, CStringGetDatum(str_))
 
 /*
  * bits_to_text
@@ -190,8 +188,8 @@ heap_page_items(PG_FUNCTION_ARGS)
 					bits_len = tuphdr->t_hoff -
 						(((char *) tuphdr->t_bits) -((char *) tuphdr));
 
-					values[11] = GET_TEXT(
-								 bits_to_text(tuphdr->t_bits, bits_len * 8));
+					values[11] = CStringGetTextDatum(
+						bits_to_text(tuphdr->t_bits, bits_len * 8));
 				}
 				else
 					nulls[11] = true;
diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c
index 230d27133b8061699ef05ea6d17f0d966d36d8ba..319886d6e6d83b38563102fcdf8acbfe4ce95a3b 100644
--- a/contrib/pageinspect/rawpage.c
+++ b/contrib/pageinspect/rawpage.c
@@ -8,7 +8,7 @@
  * Copyright (c) 2007-2008, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/contrib/pageinspect/rawpage.c,v 1.4 2008/01/01 20:31:21 tgl Exp $
+ *	  $PostgreSQL: pgsql/contrib/pageinspect/rawpage.c,v 1.5 2008/03/25 22:42:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -144,7 +144,7 @@ page_header(PG_FUNCTION_ARGS)
 	lsn = PageGetLSN(page);
 	snprintf(lsnchar, sizeof(lsnchar), "%X/%X", lsn.xlogid, lsn.xrecoff);
 
-	values[0] = DirectFunctionCall1(textin, CStringGetDatum(lsnchar));
+	values[0] = CStringGetTextDatum(lsnchar);
 	values[1] = UInt16GetDatum(PageGetTLI(page));
 	values[2] = UInt16GetDatum(page->pd_flags);
 	values[3] = UInt16GetDatum(page->pd_lower);
diff --git a/contrib/pgcrypto/pgcrypto.c b/contrib/pgcrypto/pgcrypto.c
index 6e2963ff2477b6d6f49e2407f2a67747488721f7..04c90d8672fd7739b789492993d56cf9d348110e 100644
--- a/contrib/pgcrypto/pgcrypto.c
+++ b/contrib/pgcrypto/pgcrypto.c
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgcrypto.c,v 1.26 2007/02/27 23:48:06 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/pgcrypto.c,v 1.27 2008/03/25 22:42:41 tgl Exp $
  */
 
 #include "postgres.h"
@@ -35,6 +35,7 @@
 
 #include "fmgr.h"
 #include "parser/scansup.h"
+#include "utils/builtins.h"
 
 #include "px.h"
 #include "px-crypt.h"
@@ -132,30 +133,20 @@ PG_FUNCTION_INFO_V1(pg_gen_salt);
 Datum
 pg_gen_salt(PG_FUNCTION_ARGS)
 {
-	text	   *arg0;
+	text	   *arg0 = PG_GETARG_TEXT_PP(0);
 	int			len;
-	text	   *res;
 	char		buf[PX_MAX_SALT_LEN + 1];
 
-	arg0 = PG_GETARG_TEXT_P(0);
-
-	len = VARSIZE(arg0) - VARHDRSZ;
-	len = len > PX_MAX_SALT_LEN ? PX_MAX_SALT_LEN : len;
-	memcpy(buf, VARDATA(arg0), len);
-	buf[len] = 0;
+	text_to_cstring_buffer(arg0, buf, sizeof(buf));
 	len = px_gen_salt(buf, buf, 0);
 	if (len < 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("gen_salt: %s", px_strerror(len))));
 
-	res = (text *) palloc(len + VARHDRSZ);
-	SET_VARSIZE(res, len + VARHDRSZ);
-	memcpy(VARDATA(res), buf, len);
-
 	PG_FREE_IF_COPY(arg0, 0);
 
-	PG_RETURN_TEXT_P(res);
+	PG_RETURN_TEXT_P(cstring_to_text_with_len(buf, len));
 }
 
 /* SQL function: pg_gen_salt(text, int4) returns text */
@@ -164,32 +155,21 @@ PG_FUNCTION_INFO_V1(pg_gen_salt_rounds);
 Datum
 pg_gen_salt_rounds(PG_FUNCTION_ARGS)
 {
-	text	   *arg0;
-	int			rounds;
+	text	   *arg0 = PG_GETARG_TEXT_PP(0);
+	int			rounds = PG_GETARG_INT32(1);
 	int			len;
-	text	   *res;
 	char		buf[PX_MAX_SALT_LEN + 1];
 
-	arg0 = PG_GETARG_TEXT_P(0);
-	rounds = PG_GETARG_INT32(1);
-
-	len = VARSIZE(arg0) - VARHDRSZ;
-	len = len > PX_MAX_SALT_LEN ? PX_MAX_SALT_LEN : len;
-	memcpy(buf, VARDATA(arg0), len);
-	buf[len] = 0;
+	text_to_cstring_buffer(arg0, buf, sizeof(buf));
 	len = px_gen_salt(buf, buf, rounds);
 	if (len < 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("gen_salt: %s", px_strerror(len))));
 
-	res = (text *) palloc(len + VARHDRSZ);
-	SET_VARSIZE(res, len + VARHDRSZ);
-	memcpy(VARDATA(res), buf, len);
-
 	PG_FREE_IF_COPY(arg0, 0);
 
-	PG_RETURN_TEXT_P(res);
+	PG_RETURN_TEXT_P(cstring_to_text_with_len(buf, len));
 }
 
 /* SQL function: pg_crypt(psw:text, salt:text) returns text */
@@ -198,30 +178,16 @@ PG_FUNCTION_INFO_V1(pg_crypt);
 Datum
 pg_crypt(PG_FUNCTION_ARGS)
 {
-	text	   *arg0;
-	text	   *arg1;
-	unsigned	len0,
-				len1,
-				clen;
+	text	   *arg0 = PG_GETARG_TEXT_PP(0);
+	text	   *arg1 = PG_GETARG_TEXT_PP(1);
 	char	   *buf0,
 			   *buf1,
 			   *cres,
 			   *resbuf;
 	text	   *res;
 
-	arg0 = PG_GETARG_TEXT_P(0);
-	arg1 = PG_GETARG_TEXT_P(1);
-	len0 = VARSIZE(arg0) - VARHDRSZ;
-	len1 = VARSIZE(arg1) - VARHDRSZ;
-
-	buf0 = palloc(len0 + 1);
-	buf1 = palloc(len1 + 1);
-
-	memcpy(buf0, VARDATA(arg0), len0);
-	memcpy(buf1, VARDATA(arg1), len1);
-
-	buf0[len0] = '\0';
-	buf1[len1] = '\0';
+	buf0 = text_to_cstring(arg0);
+	buf1 = text_to_cstring(arg1);
 
 	resbuf = palloc0(PX_MAX_CRYPT);
 
@@ -235,11 +201,8 @@ pg_crypt(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
 				 errmsg("crypt(3) returned NULL")));
 
-	clen = strlen(cres);
+	res = cstring_to_text(cres);
 
-	res = (text *) palloc(clen + VARHDRSZ);
-	SET_VARSIZE(res, clen + VARHDRSZ);
-	memcpy(VARDATA(res), cres, clen);
 	pfree(resbuf);
 
 	PG_FREE_IF_COPY(arg0, 0);
diff --git a/contrib/spi/autoinc.c b/contrib/spi/autoinc.c
index c748b6bf1c7d85b691981b7619a271f632997bcc..6ca09230a60124e5c1c35ac6d10efda0c34a851a 100644
--- a/contrib/spi/autoinc.c
+++ b/contrib/spi/autoinc.c
@@ -88,8 +88,7 @@ autoinc(PG_FUNCTION_ARGS)
 
 		i++;
 		chattrs[chnattrs] = attnum;
-		seqname = DirectFunctionCall1(textin,
-									  CStringGetDatum(args[i]));
+		seqname = CStringGetTextDatum(args[i]);
 		newvals[chnattrs] = DirectFunctionCall1(nextval, seqname);
 		/* nextval now returns int64; coerce down to int32 */
 		newvals[chnattrs] = Int32GetDatum((int32) DatumGetInt64(newvals[chnattrs]));
diff --git a/contrib/spi/insert_username.c b/contrib/spi/insert_username.c
index 5e709f283439915c8ade9f381b8520853d087d0c..9541677ebde19022b8df0e3f43304ad90721acfa 100644
--- a/contrib/spi/insert_username.c
+++ b/contrib/spi/insert_username.c
@@ -1,7 +1,7 @@
 /*
  * insert_username.c
  * $Modified: Thu Oct 16 08:13:42 1997 by brook $
- * $PostgreSQL: pgsql/contrib/spi/insert_username.c,v 1.15 2007/02/01 19:10:23 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/spi/insert_username.c,v 1.16 2008/03/25 22:42:42 tgl Exp $
  *
  * insert user name in response to a trigger
  * usage:  insert_username (column_name)
@@ -77,8 +77,7 @@ insert_username(PG_FUNCTION_ARGS)
 						args[0], relname)));
 
 	/* create fields containing name */
-	newval = DirectFunctionCall1(textin,
-							CStringGetDatum(GetUserNameFromId(GetUserId())));
+	newval = CStringGetTextDatum(GetUserNameFromId(GetUserId()));
 
 	/* construct new tuple */
 	rettuple = SPI_modifytuple(rel, rettuple, 1, &attnum, &newval, NULL);
diff --git a/contrib/spi/timetravel.c b/contrib/spi/timetravel.c
index 4b238fa425fbabbc57a6190594f0ded102810fda..0fd5cae09bbd73eb404301da53b20ad06a50aa1f 100644
--- a/contrib/spi/timetravel.c
+++ b/contrib/spi/timetravel.c
@@ -172,7 +172,7 @@ timetravel(PG_FUNCTION_ARGS)
 	}
 
 	/* create fields containing name */
-	newuser = DirectFunctionCall1(textin, CStringGetDatum(GetUserNameFromId(GetUserId())));
+	newuser = CStringGetTextDatum(GetUserNameFromId(GetUserId()));
 
 	nulltext = (Datum) NULL;
 
diff --git a/contrib/sslinfo/sslinfo.c b/contrib/sslinfo/sslinfo.c
index 7236203d7d81894595216d71af167e19e981ea93..a215abb8b6e76a801248117e245372b7c1728b8f 100644
--- a/contrib/sslinfo/sslinfo.c
+++ b/contrib/sslinfo/sslinfo.c
@@ -4,7 +4,7 @@
  * Written by Victor B. Wagner <vitus@cryptocom.ru>, Cryptocom LTD
  * This file is distributed under BSD-style license.
  *
- * $PostgreSQL: pgsql/contrib/sslinfo/sslinfo.c,v 1.6 2007/02/27 23:48:06 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/sslinfo/sslinfo.c,v 1.7 2008/03/25 22:42:42 tgl Exp $
  */
 
 #include "postgres.h"
@@ -133,10 +133,7 @@ ASN1_STRING_to_text(ASN1_STRING *str)
 											size - 1,
 											PG_UTF8,
 											GetDatabaseEncoding());
-	outlen = strlen(dp);
-	result = palloc(VARHDRSZ + outlen);
-	memcpy(VARDATA(result), dp, outlen);
-	SET_VARSIZE(result, VARHDRSZ + outlen);
+	result = cstring_to_text(dp);
 
 	if (dp != sp)
 		pfree(dp);
@@ -161,21 +158,12 @@ ASN1_STRING_to_text(ASN1_STRING *str)
 Datum
 X509_NAME_field_to_text(X509_NAME *name, text *fieldName)
 {
-	char	   *sp;
 	char	   *string_fieldname;
-	char	   *dp;
-	size_t		name_len = VARSIZE(fieldName) - VARHDRSZ;
 	int			nid,
-				index,
-				i;
+				index;
 	ASN1_STRING *data;
 
-	string_fieldname = palloc(name_len + 1);
-	sp = VARDATA(fieldName);
-	dp = string_fieldname;
-	for (i = 0; i < name_len; i++)
-		*dp++ = *sp++;
-	*dp = '\0';
+	string_fieldname = text_to_cstring(fieldName);
 	nid = OBJ_txt2nid(string_fieldname);
 	if (nid == NID_undef)
 		ereport(ERROR,
@@ -281,10 +269,8 @@ X509_NAME_to_text(X509_NAME *name)
 				count = X509_NAME_entry_count(name);
 	X509_NAME_ENTRY *e;
 	ASN1_STRING *v;
-
 	const char *field_name;
-	size_t		size,
-				outlen;
+	size_t		size;
 	char	   *sp;
 	char	   *dp;
 	text	   *result;
@@ -314,10 +300,7 @@ X509_NAME_to_text(X509_NAME *name)
 											GetDatabaseEncoding());
 	BIO_free(membuf);
 
-	outlen = strlen(dp);
-	result = palloc(VARHDRSZ + outlen);
-	memcpy(VARDATA(result), dp, outlen);
-	SET_VARSIZE(result, VARHDRSZ + outlen);
+	result = cstring_to_text(dp);
 
 	/*
 	 * pg_do_encoding_conversion has annoying habit of returning source
diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c
index bfac89e4146b1344675b3e00de2e311b72f7b348..793f26ed583cdd60e869a1fccc1e5c2a357df2cf 100644
--- a/contrib/tablefunc/tablefunc.c
+++ b/contrib/tablefunc/tablefunc.c
@@ -95,8 +95,6 @@ typedef struct
 	char	   *lastrowid;		/* rowid of the last tuple sent */
 }	crosstab_fctx;
 
-#define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))
-#define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
 #define xpfree(var_) \
 	do { \
 		if (var_ != NULL) \
@@ -370,7 +368,7 @@ crosstab(PG_FUNCTION_ARGS)
 	/* stuff done only on the first call of the function */
 	if (SRF_IS_FIRSTCALL())
 	{
-		char	   *sql = GET_STR(PG_GETARG_TEXT_P(0));
+		char	   *sql = text_to_cstring(PG_GETARG_TEXT_PP(0));
 		TupleDesc	tupdesc;
 		int			ret;
 		int			proc;
@@ -695,8 +693,8 @@ PG_FUNCTION_INFO_V1(crosstab_hash);
 Datum
 crosstab_hash(PG_FUNCTION_ARGS)
 {
-	char	   *sql = GET_STR(PG_GETARG_TEXT_P(0));
-	char	   *cats_sql = GET_STR(PG_GETARG_TEXT_P(1));
+	char	   *sql = text_to_cstring(PG_GETARG_TEXT_PP(0));
+	char	   *cats_sql = text_to_cstring(PG_GETARG_TEXT_PP(1));
 	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
 	TupleDesc	tupdesc;
 	MemoryContext per_query_ctx;
@@ -1052,10 +1050,10 @@ PG_FUNCTION_INFO_V1(connectby_text);
 Datum
 connectby_text(PG_FUNCTION_ARGS)
 {
-	char	   *relname = GET_STR(PG_GETARG_TEXT_P(0));
-	char	   *key_fld = GET_STR(PG_GETARG_TEXT_P(1));
-	char	   *parent_key_fld = GET_STR(PG_GETARG_TEXT_P(2));
-	char	   *start_with = GET_STR(PG_GETARG_TEXT_P(3));
+	char	   *relname = text_to_cstring(PG_GETARG_TEXT_PP(0));
+	char	   *key_fld = text_to_cstring(PG_GETARG_TEXT_PP(1));
+	char	   *parent_key_fld = text_to_cstring(PG_GETARG_TEXT_PP(2));
+	char	   *start_with = text_to_cstring(PG_GETARG_TEXT_PP(3));
 	int			max_depth = PG_GETARG_INT32(4);
 	char	   *branch_delim = NULL;
 	bool		show_branch = false;
@@ -1079,7 +1077,7 @@ connectby_text(PG_FUNCTION_ARGS)
 
 	if (fcinfo->nargs == 6)
 	{
-		branch_delim = GET_STR(PG_GETARG_TEXT_P(5));
+		branch_delim = text_to_cstring(PG_GETARG_TEXT_PP(5));
 		show_branch = true;
 	}
 	else
@@ -1129,11 +1127,11 @@ PG_FUNCTION_INFO_V1(connectby_text_serial);
 Datum
 connectby_text_serial(PG_FUNCTION_ARGS)
 {
-	char	   *relname = GET_STR(PG_GETARG_TEXT_P(0));
-	char	   *key_fld = GET_STR(PG_GETARG_TEXT_P(1));
-	char	   *parent_key_fld = GET_STR(PG_GETARG_TEXT_P(2));
-	char	   *orderby_fld = GET_STR(PG_GETARG_TEXT_P(3));
-	char	   *start_with = GET_STR(PG_GETARG_TEXT_P(4));
+	char	   *relname = text_to_cstring(PG_GETARG_TEXT_PP(0));
+	char	   *key_fld = text_to_cstring(PG_GETARG_TEXT_PP(1));
+	char	   *parent_key_fld = text_to_cstring(PG_GETARG_TEXT_PP(2));
+	char	   *orderby_fld = text_to_cstring(PG_GETARG_TEXT_PP(3));
+	char	   *start_with = text_to_cstring(PG_GETARG_TEXT_PP(4));
 	int			max_depth = PG_GETARG_INT32(5);
 	char	   *branch_delim = NULL;
 	bool		show_branch = false;
@@ -1158,7 +1156,7 @@ connectby_text_serial(PG_FUNCTION_ARGS)
 
 	if (fcinfo->nargs == 7)
 	{
-		branch_delim = GET_STR(PG_GETARG_TEXT_P(6));
+		branch_delim = text_to_cstring(PG_GETARG_TEXT_PP(6));
 		show_branch = true;
 	}
 	else
@@ -1645,9 +1643,10 @@ quote_literal_cstr(char *rawstr)
 	text	   *result_text;
 	char	   *result;
 
-	rawstr_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(rawstr)));
-	result_text = DatumGetTextP(DirectFunctionCall1(quote_literal, PointerGetDatum(rawstr_text)));
-	result = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(result_text)));
+	rawstr_text = cstring_to_text(rawstr);
+	result_text = DatumGetTextP(DirectFunctionCall1(quote_literal,
+													PointerGetDatum(rawstr_text)));
+	result = text_to_cstring(result_text);
 
 	return result;
 }
diff --git a/contrib/tsearch2/tsearch2.c b/contrib/tsearch2/tsearch2.c
index 9dc5eb3bdbf8f2633122853dec22398f80248287..7754f5740269a11eeb4682efbdc4353495b4cb28 100644
--- a/contrib/tsearch2/tsearch2.c
+++ b/contrib/tsearch2/tsearch2.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/contrib/tsearch2/tsearch2.c,v 1.5 2008/01/01 19:45:45 momjian Exp $
+ *	  $PostgreSQL: pgsql/contrib/tsearch2/tsearch2.c,v 1.6 2008/03/25 22:42:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -41,14 +41,9 @@ static Oid	current_parser_oid = InvalidOid;
 		fcinfo->nargs++;								\
 	} while (0)
 
-#define TextPGetCString(t) \
-	DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(t)))
-#define CStringGetTextP(c) \
-	DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(c)))
-
 #define TextGetObjectId(infunction, text) \
 	DatumGetObjectId(DirectFunctionCall1(infunction, \
-					 DirectFunctionCall1(textout, PointerGetDatum(text))))
+					 CStringGetDatum(text_to_cstring(text))))
 
 #define UNSUPPORTED_FUNCTION(name)						\
 	Datum name(PG_FUNCTION_ARGS);						\
@@ -151,7 +146,7 @@ UNSUPPORTED_FUNCTION(tsa_get_covers);
 Datum
 tsa_lexize_byname(PG_FUNCTION_ARGS)
 {
-	text	   *dictname = PG_GETARG_TEXT_P(0);
+	text	   *dictname = PG_GETARG_TEXT_PP(0);
 	Datum		arg1 = PG_GETARG_DATUM(1);
 
 	return DirectFunctionCall2(ts_lexize,
@@ -192,10 +187,10 @@ tsa_set_curdict(PG_FUNCTION_ARGS)
 Datum
 tsa_set_curdict_byname(PG_FUNCTION_ARGS)
 {
-	text	   *name = PG_GETARG_TEXT_P(0);
+	text	   *name = PG_GETARG_TEXT_PP(0);
 	Oid			dict_oid;
 
-	dict_oid = TSDictionaryGetDictid(stringToQualifiedNameList(TextPGetCString(name)), false);
+	dict_oid = TSDictionaryGetDictid(stringToQualifiedNameList(text_to_cstring(name)), false);
 
 	current_dictionary_oid = dict_oid;
 
@@ -231,10 +226,10 @@ tsa_set_curprs(PG_FUNCTION_ARGS)
 Datum
 tsa_set_curprs_byname(PG_FUNCTION_ARGS)
 {
-	text	   *name = PG_GETARG_TEXT_P(0);
+	text	   *name = PG_GETARG_TEXT_PP(0);
 	Oid			parser_oid;
 
-	parser_oid = TSParserGetPrsid(stringToQualifiedNameList(TextPGetCString(name)), false);
+	parser_oid = TSParserGetPrsid(stringToQualifiedNameList(text_to_cstring(name)), false);
 
 	current_parser_oid = parser_oid;
 
@@ -272,10 +267,10 @@ tsa_set_curcfg(PG_FUNCTION_ARGS)
 Datum
 tsa_set_curcfg_byname(PG_FUNCTION_ARGS)
 {
-	text	   *arg0 = PG_GETARG_TEXT_P(0);
+	text	   *arg0 = PG_GETARG_TEXT_PP(0);
 	char	   *name;
 
-	name = TextPGetCString(arg0);
+	name = text_to_cstring(arg0);
 
 	set_config_option("default_text_search_config", name,
 					  PGC_USERSET,
@@ -290,7 +285,7 @@ tsa_set_curcfg_byname(PG_FUNCTION_ARGS)
 Datum
 tsa_to_tsvector_name(PG_FUNCTION_ARGS)
 {
-	text	   *cfgname = PG_GETARG_TEXT_P(0);
+	text	   *cfgname = PG_GETARG_TEXT_PP(0);
 	Datum		arg1 = PG_GETARG_DATUM(1);
 	Oid			config_oid;
 
@@ -304,7 +299,7 @@ tsa_to_tsvector_name(PG_FUNCTION_ARGS)
 Datum
 tsa_to_tsquery_name(PG_FUNCTION_ARGS)
 {
-	text	   *cfgname = PG_GETARG_TEXT_P(0);
+	text	   *cfgname = PG_GETARG_TEXT_PP(0);
 	Datum		arg1 = PG_GETARG_DATUM(1);
 	Oid			config_oid;
 
@@ -319,7 +314,7 @@ tsa_to_tsquery_name(PG_FUNCTION_ARGS)
 Datum
 tsa_plainto_tsquery_name(PG_FUNCTION_ARGS)
 {
-	text	   *cfgname = PG_GETARG_TEXT_P(0);
+	text	   *cfgname = PG_GETARG_TEXT_PP(0);
 	Datum		arg1 = PG_GETARG_DATUM(1);
 	Oid			config_oid;
 
@@ -341,7 +336,7 @@ tsa_headline_byname(PG_FUNCTION_ARGS)
 
 	/* first parameter has to be converted to oid */
 	config_oid = DatumGetObjectId(DirectFunctionCall1(regconfigin,
-										DirectFunctionCall1(textout, arg0)));
+								CStringGetDatum(TextDatumGetCString(arg0))));
 
 	if (PG_NARGS() == 3)
 		result = DirectFunctionCall3(ts_headline_byid,
diff --git a/contrib/uuid-ossp/uuid-ossp.c b/contrib/uuid-ossp/uuid-ossp.c
index 456ec5728b856c41cf0428a54d3a26878383d8ff..7bdf5ee5140f481abfa03176e42f2ccfea2cae10 100644
--- a/contrib/uuid-ossp/uuid-ossp.c
+++ b/contrib/uuid-ossp/uuid-ossp.c
@@ -4,7 +4,7 @@
  *
  * Copyright (c) 2007-2008 PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/contrib/uuid-ossp/uuid-ossp.c,v 1.7 2008/01/01 20:31:21 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/uuid-ossp/uuid-ossp.c,v 1.8 2008/03/25 22:42:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -214,7 +214,7 @@ uuid_generate_v35_internal(int mode, pg_uuid_t *ns, text *name)
 
 	result = uuid_generate_internal(mode,
 									ns_uuid,
-	   DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(name))));
+									text_to_cstring(name));
 
 	rc = uuid_destroy(ns_uuid);
 	if (rc != UUID_RC_OK)
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index b02f957777289e200547e83ef40462d529c7531a..52cc3d379fd3180c7120bb8a67ae2e14f4e5ea2f 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -55,11 +55,6 @@ Datum		xpath_table(PG_FUNCTION_ARGS);
 char	   *errbuf;				/* per line error buffer */
 char	   *pgxml_errorMsg = NULL;		/* overall error message */
 
-/* Convenience macros */
-
-#define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))
-#define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
-
 #define ERRBUF_SIZE 200
 
 /* memory handling passthrough functions (e.g. palloc, pstrdup are
@@ -651,11 +646,11 @@ xpath_table(PG_FUNCTION_ARGS)
 	MemoryContext oldcontext;
 
 /* Function parameters */
-	char	   *pkeyfield = GET_STR(PG_GETARG_TEXT_P(0));
-	char	   *xmlfield = GET_STR(PG_GETARG_TEXT_P(1));
-	char	   *relname = GET_STR(PG_GETARG_TEXT_P(2));
-	char	   *xpathset = GET_STR(PG_GETARG_TEXT_P(3));
-	char	   *condition = GET_STR(PG_GETARG_TEXT_P(4));
+	char	   *pkeyfield = text_to_cstring(PG_GETARG_TEXT_PP(0));
+	char	   *xmlfield = text_to_cstring(PG_GETARG_TEXT_PP(1));
+	char	   *relname = text_to_cstring(PG_GETARG_TEXT_PP(2));
+	char	   *xpathset = text_to_cstring(PG_GETARG_TEXT_PP(3));
+	char	   *condition = text_to_cstring(PG_GETARG_TEXT_PP(4));
 
 	char	  **values;
 	xmlChar   **xpaths;
diff --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c
index b89102245c5e6c61a4b785902bb1a6e4fa9411e9..f15fabcb3c52275226efb303da9f07cb635920e9 100644
--- a/contrib/xml2/xslt_proc.c
+++ b/contrib/xml2/xslt_proc.c
@@ -22,13 +22,10 @@
 
 
 /* declarations to come from xpath.c */
-
 extern void elog_error(int level, char *explain, int force);
 extern void pgxml_parser_init();
 extern xmlChar *pgxml_texttoxmlchar(text *textstring);
 
-#define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
-
 /* local defs */
 static void parse_params(const char **params, text *paramstr);
 
@@ -76,7 +73,7 @@ xslt_process(PG_FUNCTION_ARGS)
 	if (VARDATA(doct)[0] == '<')
 		doctree = xmlParseMemory((char *) VARDATA(doct), VARSIZE(doct) - VARHDRSZ);
 	else
-		doctree = xmlParseFile(GET_STR(doct));
+		doctree = xmlParseFile(text_to_cstring(doct));
 
 	if (doctree == NULL)
 	{
@@ -102,7 +99,7 @@ xslt_process(PG_FUNCTION_ARGS)
 		stylesheet = xsltParseStylesheetDoc(ssdoc);
 	}
 	else
-		stylesheet = xsltParseStylesheetFile((xmlChar *) GET_STR(ssheet));
+		stylesheet = xsltParseStylesheetFile((xmlChar *) text_to_cstring(ssheet));
 
 
 	if (stylesheet == NULL)
@@ -145,7 +142,7 @@ parse_params(const char **params, text *paramstr)
 	char	   *nvsep = "=";
 	char	   *itsep = ",";
 
-	pstr = GET_STR(paramstr);
+	pstr = text_to_cstring(paramstr);
 
 	pos = pstr;
 
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index d488c203d3df6f22a163a09163369cacd50e67de..a28d8170a4cf45418f437b80786f0447ef71bc7b 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.60 2008/02/12 04:09:44 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.61 2008/03/25 22:42:42 tgl Exp $ -->
 
 <chapter id="spi">
  <title>Server Programming Interface</title>
@@ -3343,8 +3343,7 @@ execq(text *sql, int cnt)
     int proc;
 
     /* Convert given text object to a C string */
-    command = DatumGetCString(DirectFunctionCall1(textout,
-                                                  PointerGetDatum(sql)));
+    command = text_to_cstring(sql);
 
     SPI_connect();
     
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 48e9080b60d0c8937cc31af16b3dfb0d95b32f05..fc5b6ebdcac764b7e4d87ffc7f3f882e68a81d34 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.8 2008/01/01 19:45:46 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.9 2008/03/25 22:42:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -180,7 +180,7 @@ untransformRelOptions(Datum options)
 		char	   *p;
 		Node	   *val = NULL;
 
-		s = DatumGetCString(DirectFunctionCall1(textout, optiondatums[i]));
+		s = TextDatumGetCString(optiondatums[i]);
 		p = strchr(s, '=');
 		if (p)
 		{
@@ -266,7 +266,7 @@ parseRelOptions(Datum options, int numkeywords, const char *const * keywords,
 			char	   *s;
 			char	   *p;
 
-			s = DatumGetCString(DirectFunctionCall1(textout, optiondatums[i]));
+			s = TextDatumGetCString(optiondatums[i]);
 			p = strchr(s, '=');
 			if (p)
 				*p = '\0';
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index a51f884c11612f8e61ef461c40aa1f335fb5abd6..b8d3913cd03450f5325d062c0afc5a7bff46243a 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *		$PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.40 2008/03/17 02:18:55 tgl Exp $
+ *		$PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.41 2008/03/25 22:42:42 tgl Exp $
  *
  * NOTES
  *		Each global transaction is associated with a global transaction
@@ -623,7 +623,7 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
 		MemSet(nulls, 0, sizeof(nulls));
 
 		values[0] = TransactionIdGetDatum(gxact->proc.xid);
-		values[1] = DirectFunctionCall1(textin, CStringGetDatum(gxact->gid));
+		values[1] = CStringGetTextDatum(gxact->gid);
 		values[2] = TimestampTzGetDatum(gxact->prepared_at);
 		values[3] = ObjectIdGetDatum(gxact->owner);
 		values[4] = ObjectIdGetDatum(gxact->proc.databaseId);
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 3990f1d863e6a8da519322deaf781a0f6de0dbc4..1b6a58f6616f040e10eda72c6c2973bfc051aff4 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.294 2008/03/10 02:13:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.295 2008/03/25 22:42:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -6380,7 +6380,6 @@ Datum
 pg_start_backup(PG_FUNCTION_ARGS)
 {
 	text	   *backupid = PG_GETARG_TEXT_P(0);
-	text	   *result;
 	char	   *backupidstr;
 	XLogRecPtr	checkpointloc;
 	XLogRecPtr	startpoint;
@@ -6410,8 +6409,7 @@ pg_start_backup(PG_FUNCTION_ARGS)
 				 errhint("archive_command must be defined before "
 						 "online backups can be made safely.")));
 
-	backupidstr = DatumGetCString(DirectFunctionCall1(textout,
-												 PointerGetDatum(backupid)));
+	backupidstr = text_to_cstring(backupid);
 
 	/*
 	 * Mark backup active in shared memory.  We must do full-page WAL writes
@@ -6531,9 +6529,7 @@ pg_start_backup(PG_FUNCTION_ARGS)
 	 */
 	snprintf(xlogfilename, sizeof(xlogfilename), "%X/%X",
 			 startpoint.xlogid, startpoint.xrecoff);
-	result = DatumGetTextP(DirectFunctionCall1(textin,
-											 CStringGetDatum(xlogfilename)));
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(xlogfilename));
 }
 
 /*
@@ -6547,7 +6543,6 @@ pg_start_backup(PG_FUNCTION_ARGS)
 Datum
 pg_stop_backup(PG_FUNCTION_ARGS)
 {
-	text	   *result;
 	XLogRecPtr	startpoint;
 	XLogRecPtr	stoppoint;
 	pg_time_t	stamp_time;
@@ -6669,9 +6664,7 @@ pg_stop_backup(PG_FUNCTION_ARGS)
 	 */
 	snprintf(stopxlogfilename, sizeof(stopxlogfilename), "%X/%X",
 			 stoppoint.xlogid, stoppoint.xrecoff);
-	result = DatumGetTextP(DirectFunctionCall1(textin,
-										 CStringGetDatum(stopxlogfilename)));
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(stopxlogfilename));
 }
 
 /*
@@ -6680,7 +6673,6 @@ pg_stop_backup(PG_FUNCTION_ARGS)
 Datum
 pg_switch_xlog(PG_FUNCTION_ARGS)
 {
-	text	   *result;
 	XLogRecPtr	switchpoint;
 	char		location[MAXFNAMELEN];
 
@@ -6696,9 +6688,7 @@ pg_switch_xlog(PG_FUNCTION_ARGS)
 	 */
 	snprintf(location, sizeof(location), "%X/%X",
 			 switchpoint.xlogid, switchpoint.xrecoff);
-	result = DatumGetTextP(DirectFunctionCall1(textin,
-											   CStringGetDatum(location)));
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(location));
 }
 
 /*
@@ -6711,7 +6701,6 @@ pg_switch_xlog(PG_FUNCTION_ARGS)
 Datum
 pg_current_xlog_location(PG_FUNCTION_ARGS)
 {
-	text	   *result;
 	char		location[MAXFNAMELEN];
 
 	/* Make sure we have an up-to-date local LogwrtResult */
@@ -6726,10 +6715,7 @@ pg_current_xlog_location(PG_FUNCTION_ARGS)
 
 	snprintf(location, sizeof(location), "%X/%X",
 			 LogwrtResult.Write.xlogid, LogwrtResult.Write.xrecoff);
-
-	result = DatumGetTextP(DirectFunctionCall1(textin,
-											   CStringGetDatum(location)));
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(location));
 }
 
 /*
@@ -6740,7 +6726,6 @@ pg_current_xlog_location(PG_FUNCTION_ARGS)
 Datum
 pg_current_xlog_insert_location(PG_FUNCTION_ARGS)
 {
-	text	   *result;
 	XLogCtlInsert *Insert = &XLogCtl->Insert;
 	XLogRecPtr	current_recptr;
 	char		location[MAXFNAMELEN];
@@ -6754,10 +6739,7 @@ pg_current_xlog_insert_location(PG_FUNCTION_ARGS)
 
 	snprintf(location, sizeof(location), "%X/%X",
 			 current_recptr.xlogid, current_recptr.xrecoff);
-
-	result = DatumGetTextP(DirectFunctionCall1(textin,
-											   CStringGetDatum(location)));
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(location));
 }
 
 /*
@@ -6789,8 +6771,7 @@ pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
 	/*
 	 * Read input and parse
 	 */
-	locationstr = DatumGetCString(DirectFunctionCall1(textout,
-												 PointerGetDatum(location)));
+	locationstr = text_to_cstring(location);
 
 	if (sscanf(locationstr, "%X/%X", &uxlogid, &uxrecoff) != 2)
 		ereport(ERROR,
@@ -6819,8 +6800,7 @@ pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
 	XLByteToPrevSeg(locationpoint, xlogid, xlogseg);
 	XLogFileName(xlogfilename, ThisTimeLineID, xlogid, xlogseg);
 
-	values[0] = DirectFunctionCall1(textin,
-									CStringGetDatum(xlogfilename));
+	values[0] = CStringGetTextDatum(xlogfilename);
 	isnull[0] = false;
 
 	/*
@@ -6849,7 +6829,6 @@ Datum
 pg_xlogfile_name(PG_FUNCTION_ARGS)
 {
 	text	   *location = PG_GETARG_TEXT_P(0);
-	text	   *result;
 	char	   *locationstr;
 	unsigned int uxlogid;
 	unsigned int uxrecoff;
@@ -6858,8 +6837,7 @@ pg_xlogfile_name(PG_FUNCTION_ARGS)
 	XLogRecPtr	locationpoint;
 	char		xlogfilename[MAXFNAMELEN];
 
-	locationstr = DatumGetCString(DirectFunctionCall1(textout,
-												 PointerGetDatum(location)));
+	locationstr = text_to_cstring(location);
 
 	if (sscanf(locationstr, "%X/%X", &uxlogid, &uxrecoff) != 2)
 		ereport(ERROR,
@@ -6873,9 +6851,7 @@ pg_xlogfile_name(PG_FUNCTION_ARGS)
 	XLByteToPrevSeg(locationpoint, xlogid, xlogseg);
 	XLogFileName(xlogfilename, ThisTimeLineID, xlogid, xlogseg);
 
-	result = DatumGetTextP(DirectFunctionCall1(textin,
-											 CStringGetDatum(xlogfilename)));
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(xlogfilename));
 }
 
 /*
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 3f8c7eab47bc0e9eb149b71f8aaa383ec302f255..974eec8a06a41570358f7830ba0aeb480dd63f24 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.327 2008/01/01 19:45:48 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.328 2008/03/25 22:42:42 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1459,10 +1459,8 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin)
 	 */
 	values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
 	values[Anum_pg_attrdef_adnum - 1] = attnum;
-	values[Anum_pg_attrdef_adbin - 1] = DirectFunctionCall1(textin,
-													 CStringGetDatum(adbin));
-	values[Anum_pg_attrdef_adsrc - 1] = DirectFunctionCall1(textin,
-													 CStringGetDatum(adsrc));
+	values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
+	values[Anum_pg_attrdef_adsrc - 1] = CStringGetTextDatum(adsrc);
 
 	adrel = heap_open(AttrDefaultRelationId, RowExclusiveLock);
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index ed30b09b42a50fc019101aef96a214fdab146899..4188eec289c9d6ad323dd18bf96c84e33f40c5ea 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.292 2008/01/30 19:46:48 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.293 2008/03/25 22:42:42 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -374,8 +374,7 @@ UpdateIndexRelation(Oid indexoid,
 		char	   *exprsString;
 
 		exprsString = nodeToString(indexInfo->ii_Expressions);
-		exprsDatum = DirectFunctionCall1(textin,
-										 CStringGetDatum(exprsString));
+		exprsDatum = CStringGetTextDatum(exprsString);
 		pfree(exprsString);
 	}
 	else
@@ -390,8 +389,7 @@ UpdateIndexRelation(Oid indexoid,
 		char	   *predString;
 
 		predString = nodeToString(make_ands_explicit(indexInfo->ii_Predicate));
-		predDatum = DirectFunctionCall1(textin,
-										CStringGetDatum(predString));
+		predDatum = CStringGetTextDatum(predString);
 		pfree(predString);
 	}
 	else
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index bfdd429b23ae3b467365896e39ca84ee0f18b625..c88f9973b975ea54c3b48eb93a90b62a5d591427 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.90 2008/01/11 18:39:40 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.91 2008/03/25 22:42:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -232,8 +232,7 @@ AggregateCreate(const char *aggName,
 	values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
 	values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
 	if (agginitval)
-		values[Anum_pg_aggregate_agginitval - 1] =
-			DirectFunctionCall1(textin, CStringGetDatum(agginitval));
+		values[Anum_pg_aggregate_agginitval - 1] = CStringGetTextDatum(agginitval);
 	else
 		nulls[Anum_pg_aggregate_agginitval - 1] = 'n';
 
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index c25cfaab35bf45c191217c94b07b5167297db922..2de30557801440090ed8fe8ed9ea49114481298f 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.38 2008/01/17 18:56:54 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.39 2008/03/25 22:42:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -174,8 +174,7 @@ CreateConstraintEntry(const char *constraintName,
 	 * initialize the binary form of the check constraint.
 	 */
 	if (conBin)
-		values[Anum_pg_constraint_conbin - 1] = DirectFunctionCall1(textin,
-													CStringGetDatum(conBin));
+		values[Anum_pg_constraint_conbin - 1] = CStringGetTextDatum(conBin);
 	else
 		nulls[Anum_pg_constraint_conbin - 1] = 'n';
 
@@ -183,8 +182,7 @@ CreateConstraintEntry(const char *constraintName,
 	 * initialize the text form of the check constraint
 	 */
 	if (conSrc)
-		values[Anum_pg_constraint_consrc - 1] = DirectFunctionCall1(textin,
-													CStringGetDatum(conSrc));
+		values[Anum_pg_constraint_consrc - 1] = CStringGetTextDatum(conSrc);
 	else
 		nulls[Anum_pg_constraint_consrc - 1] = 'n';
 
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index f86b742cada7bd578e36db3b950cda53c08de03b..c099d95c0592f64ac7b158361ba221a72f37b381 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.149 2008/03/18 22:04:14 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.150 2008/03/25 22:42:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -248,10 +248,8 @@ ProcedureCreate(const char *procedureName,
 		values[Anum_pg_proc_proargnames - 1] = parameterNames;
 	else
 		nulls[Anum_pg_proc_proargnames - 1] = 'n';
-	values[Anum_pg_proc_prosrc - 1] = DirectFunctionCall1(textin,
-													CStringGetDatum(prosrc));
-	values[Anum_pg_proc_probin - 1] = DirectFunctionCall1(textin,
-													CStringGetDatum(probin));
+	values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc);
+	values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin);
 	if (proconfig != PointerGetDatum(NULL))
 		values[Anum_pg_proc_proconfig - 1] = proconfig;
 	else
@@ -449,7 +447,7 @@ fmgr_internal_validator(PG_FUNCTION_ARGS)
 	tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
 	if (isnull)
 		elog(ERROR, "null prosrc");
-	prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp));
+	prosrc = TextDatumGetCString(tmp);
 
 	if (fmgr_internal_function(prosrc) == InvalidOid)
 		ereport(ERROR,
@@ -499,12 +497,12 @@ fmgr_c_validator(PG_FUNCTION_ARGS)
 	tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
 	if (isnull)
 		elog(ERROR, "null prosrc");
-	prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp));
+	prosrc = TextDatumGetCString(tmp);
 
 	tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_probin, &isnull);
 	if (isnull)
 		elog(ERROR, "null probin");
-	probin = DatumGetCString(DirectFunctionCall1(textout, tmp));
+	probin = TextDatumGetCString(tmp);
 
 	(void) load_external_function(probin, prosrc, true, &libraryhandle);
 	(void) fetch_finfo_record(libraryhandle, prosrc);
@@ -576,7 +574,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
 		if (isnull)
 			elog(ERROR, "null prosrc");
 
-		prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp));
+		prosrc = TextDatumGetCString(tmp);
 
 		/*
 		 * Setup error traceback support for ereport().
@@ -631,7 +629,7 @@ sql_function_parse_error_callback(void *arg)
 	tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
 	if (isnull)
 		elog(ERROR, "null prosrc");
-	prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp));
+	prosrc = TextDatumGetCString(tmp);
 
 	if (!function_parse_error_transpose(prosrc))
 	{
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index a654f19dbbd87b7df06ff1a66f8ce44827e0678b..cdbd55c5292562880add8cb32e434a1841a39556 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.116 2008/03/19 18:38:30 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.117 2008/03/25 22:42:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -275,8 +275,7 @@ TypeCreate(Oid newTypeOid,
 	 * course.
 	 */
 	if (defaultTypeBin)
-		values[i] = DirectFunctionCall1(textin,
-										CStringGetDatum(defaultTypeBin));
+		values[i] = CStringGetTextDatum(defaultTypeBin);
 	else
 		nulls[i] = 'n';
 	i++;						/* typdefaultbin */
@@ -285,8 +284,7 @@ TypeCreate(Oid newTypeOid,
 	 * initialize the default value for this type.
 	 */
 	if (defaultTypeValue)
-		values[i] = DirectFunctionCall1(textin,
-										CStringGetDatum(defaultTypeValue));
+		values[i] = CStringGetTextDatum(defaultTypeValue);
 	else
 		nulls[i] = 'n';
 	i++;						/* typdefault */
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 76c74cae1b66117da67a215b187fdfcedabd688c..ec7923d767380377ecee89a1554ea264e2203cbb 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -7,7 +7,7 @@
  * Copyright (c) 1996-2008, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.100 2008/01/01 19:45:48 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.101 2008/03/25 22:42:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -215,7 +215,7 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
 		values[i++] = ObjectIdGetDatum(oid);
 		values[i++] = ObjectIdGetDatum(classoid);
 		values[i++] = Int32GetDatum(subid);
-		values[i++] = DirectFunctionCall1(textin, CStringGetDatum(comment));
+		values[i++] = CStringGetTextDatum(comment);
 	}
 
 	/* Use the index to search for a matching old tuple */
@@ -314,7 +314,7 @@ CreateSharedComments(Oid oid, Oid classoid, char *comment)
 		i = 0;
 		values[i++] = ObjectIdGetDatum(oid);
 		values[i++] = ObjectIdGetDatum(classoid);
-		values[i++] = DirectFunctionCall1(textin, CStringGetDatum(comment));
+		values[i++] = CStringGetTextDatum(comment);
 	}
 
 	/* Use the index to search for a matching old tuple */
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 066a8c9898e79ff01d406d25c9d837c3fad0ea14..c04ca079bdf378cdb0fabc234aebbb98b4e510e3 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.88 2008/01/01 19:45:49 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.89 2008/03/25 22:42:42 tgl Exp $
  *
  * DESCRIPTION
  *	  These routines take the parse tree and pick out the
@@ -237,8 +237,7 @@ examine_parameter_list(List *parameters, Oid languageOid,
 
 		if (fp->name && fp->name[0])
 		{
-			paramNames[i] = DirectFunctionCall1(textin,
-												CStringGetDatum(fp->name));
+			paramNames[i] = CStringGetTextDatum(fp->name);
 			have_names = true;
 		}
 
@@ -269,8 +268,7 @@ examine_parameter_list(List *parameters, Oid languageOid,
 		for (i = 0; i < parameterCount; i++)
 		{
 			if (paramNames[i] == PointerGetDatum(NULL))
-				paramNames[i] = DirectFunctionCall1(textin,
-													CStringGetDatum(""));
+				paramNames[i] = CStringGetTextDatum("");
 		}
 		*parameterNames = construct_array(paramNames, parameterCount, TEXTOID,
 										  -1, false, 'i');
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 9db486581ed543362f97c7ae0048e1adf30085df..e9a0aaf050d6352ffa8ad2838fbc8bf151947873 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -10,7 +10,7 @@
  * Copyright (c) 2002-2008, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.81 2008/03/25 19:26:53 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.82 2008/03/25 22:42:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -772,14 +772,12 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
 
 			MemSet(nulls, 0, sizeof(nulls));
 
-			values[0] = DirectFunctionCall1(textin,
-									  CStringGetDatum(prep_stmt->stmt_name));
+			values[0] = CStringGetTextDatum(prep_stmt->stmt_name);
 
 			if (prep_stmt->plansource->query_string == NULL)
 				nulls[1] = true;
 			else
-				values[1] = DirectFunctionCall1(textin,
-					   CStringGetDatum(prep_stmt->plansource->query_string));
+				values[1] = CStringGetTextDatum(prep_stmt->plansource->query_string);
 
 			values[2] = TimestampTzGetDatum(prep_stmt->prepare_time);
 			values[3] = build_regtype_array(prep_stmt->plansource->param_types,
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index fa79f55950b80554d918ab51c4da2d9fade3f14c..8e90db3708148830b7d1caa1fe103df10a974030 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.74 2008/01/01 19:45:49 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.75 2008/03/25 22:42:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -360,20 +360,17 @@ find_language_template(const char *languageName)
 		datum = heap_getattr(tup, Anum_pg_pltemplate_tmplhandler,
 							 RelationGetDescr(rel), &isnull);
 		if (!isnull)
-			result->tmplhandler =
-				DatumGetCString(DirectFunctionCall1(textout, datum));
+			result->tmplhandler = TextDatumGetCString(datum);
 
 		datum = heap_getattr(tup, Anum_pg_pltemplate_tmplvalidator,
 							 RelationGetDescr(rel), &isnull);
 		if (!isnull)
-			result->tmplvalidator =
-				DatumGetCString(DirectFunctionCall1(textout, datum));
+			result->tmplvalidator = TextDatumGetCString(datum);
 
 		datum = heap_getattr(tup, Anum_pg_pltemplate_tmpllibrary,
 							 RelationGetDescr(rel), &isnull);
 		if (!isnull)
-			result->tmpllibrary =
-				DatumGetCString(DirectFunctionCall1(textout, datum));
+			result->tmpllibrary = TextDatumGetCString(datum);
 
 		/* Ignore template if handler or library info is missing */
 		if (!result->tmplhandler || !result->tmpllibrary)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index bd7786a918d9528db5557ad7b8e68cda9aaaa0e7..a11a6844cbd1a430fb0edc434bbda932b7b68368 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.243 2008/03/19 18:38:30 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.244 2008/03/25 22:42:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -6183,7 +6183,7 @@ decompile_conbin(HeapTuple contup, TupleDesc tupdesc)
 
 	expr = DirectFunctionCall2(pg_get_expr, attr,
 							   ObjectIdGetDatum(con->conrelid));
-	return DatumGetCString(DirectFunctionCall1(textout, expr));
+	return TextDatumGetCString(expr);
 }
 
 /*
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index d8bff7c32203e23912aa8b69c0b5ee2b8bf5e0ac..8845bae8427e980a4d90cbfb672eb3d5bf7aafc4 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.53 2008/01/01 19:45:49 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.54 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -282,7 +282,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
 	values[Anum_pg_tablespace_spcowner - 1] =
 		ObjectIdGetDatum(ownerId);
 	values[Anum_pg_tablespace_spclocation - 1] =
-		DirectFunctionCall1(textin, CStringGetDatum(location));
+		CStringGetTextDatum(location);
 	nulls[Anum_pg_tablespace_spcacl - 1] = 'n';
 
 	tuple = heap_formtuple(rel->rd_att, values, nulls);
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 1ec63114ab5db39a6b1a55bd575653c5159a1015..c1e63260a3ba411d5be2f98a065aad3f032b18c8 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tsearchcmds.c,v 1.9 2008/01/01 19:45:49 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tsearchcmds.c,v 1.10 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1999,7 +1999,7 @@ serialize_deflist(List *deflist)
 			appendStringInfo(&buf, ", ");
 	}
 
-	result = CStringGetTextP(buf.data);
+	result = cstring_to_text_with_len(buf.data, buf.len);
 	pfree(buf.data);
 	return result;
 }
@@ -2099,7 +2099,7 @@ deserialize_deflist(Datum txt)
 					ereport(ERROR,
 							(errcode(ERRCODE_SYNTAX_ERROR),
 							 errmsg("invalid parameter list format: \"%s\"",
-									TextPGetCString(in))));
+									text_to_cstring(in))));
 				break;
 			case CS_WAITVALUE:
 				if (*ptr == '\'')
@@ -2210,7 +2210,7 @@ deserialize_deflist(Datum txt)
 		ereport(ERROR,
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("invalid parameter list format: \"%s\"",
-						TextPGetCString(in))));
+						text_to_cstring(in))));
 
 	pfree(workspace);
 
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 982588e04a616c60b1f4bf12f59ef45e14051d17..d67ae2c2db8ae254b51ea38e34d27d012a947136 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.114 2008/03/19 18:38:30 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.115 2008/03/25 22:42:43 tgl Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -697,13 +697,13 @@ DefineDomain(CreateDomainStmt *stmt)
 	datum = SysCacheGetAttr(TYPEOID, typeTup,
 							Anum_pg_type_typdefault, &isnull);
 	if (!isnull)
-		defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum));
+		defaultValue = TextDatumGetCString(datum);
 
 	/* Inherited default binary value */
 	datum = SysCacheGetAttr(TYPEOID, typeTup,
 							Anum_pg_type_typdefaultbin, &isnull);
 	if (!isnull)
-		defaultValueBin = DatumGetCString(DirectFunctionCall1(textout, datum));
+		defaultValueBin = TextDatumGetCString(datum);
 
 	/*
 	 * Run through constraints manually to avoid the additional processing
@@ -1497,12 +1497,10 @@ AlterDomainDefault(List *names, Node *defaultRaw)
 			/*
 			 * Form an updated tuple with the new default and write it back.
 			 */
-			new_record[Anum_pg_type_typdefaultbin - 1] = DirectFunctionCall1(textin,
-								 CStringGetDatum(nodeToString(defaultExpr)));
+			new_record[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(nodeToString(defaultExpr));
 
 			new_record_repl[Anum_pg_type_typdefaultbin - 1] = 'r';
-			new_record[Anum_pg_type_typdefault - 1] = DirectFunctionCall1(textin,
-											  CStringGetDatum(defaultValue));
+			new_record[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultValue);
 			new_record_repl[Anum_pg_type_typdefault - 1] = 'r';
 		}
 	}
@@ -2292,9 +2290,7 @@ GetDomainConstraints(Oid typeOid)
 				elog(ERROR, "domain \"%s\" constraint \"%s\" has NULL conbin",
 					 NameStr(typTup->typname), NameStr(c->conname));
 
-			check_expr = (Expr *)
-				stringToNode(DatumGetCString(DirectFunctionCall1(textout,
-																 val)));
+			check_expr = (Expr *) stringToNode(TextDatumGetCString(val));
 
 			/* ExecInitExpr assumes we already fixed opfuncids */
 			fix_opfuncids((Node *) check_expr);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 2b790227f32d38b9f26a093e4f69c1bcd1835a03..77432927d3ddd2f5af0aff10ae57a93ea0565526 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.179 2008/03/24 19:47:35 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.180 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -311,14 +311,14 @@ CreateRole(CreateRoleStmt *stmt)
 	{
 		if (!encrypt_password || isMD5(password))
 			new_record[Anum_pg_authid_rolpassword - 1] =
-				DirectFunctionCall1(textin, CStringGetDatum(password));
+				CStringGetTextDatum(password);
 		else
 		{
 			if (!pg_md5_encrypt(password, stmt->role, strlen(stmt->role),
 								encrypted_password))
 				elog(ERROR, "password encryption failed");
 			new_record[Anum_pg_authid_rolpassword - 1] =
-				DirectFunctionCall1(textin, CStringGetDatum(encrypted_password));
+				CStringGetTextDatum(encrypted_password);
 		}
 	}
 	else
@@ -639,14 +639,14 @@ AlterRole(AlterRoleStmt *stmt)
 	{
 		if (!encrypt_password || isMD5(password))
 			new_record[Anum_pg_authid_rolpassword - 1] =
-				DirectFunctionCall1(textin, CStringGetDatum(password));
+				CStringGetTextDatum(password);
 		else
 		{
 			if (!pg_md5_encrypt(password, stmt->role, strlen(stmt->role),
 								encrypted_password))
 				elog(ERROR, "password encryption failed");
 			new_record[Anum_pg_authid_rolpassword - 1] =
-				DirectFunctionCall1(textin, CStringGetDatum(encrypted_password));
+				CStringGetTextDatum(encrypted_password);
 		}
 		new_record_repl[Anum_pg_authid_rolpassword - 1] = 'r';
 	}
@@ -1060,7 +1060,7 @@ RenameRole(const char *oldname, const char *newname)
 
 	datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
 
-	if (!isnull && isMD5(DatumGetCString(DirectFunctionCall1(textout, datum))))
+	if (!isnull && isMD5(TextDatumGetCString(datum)))
 	{
 		/* MD5 uses the username as salt, so just clear it on a rename */
 		repl_repl[Anum_pg_authid_rolpassword - 1] = 'r';
diff --git a/src/backend/executor/execCurrent.c b/src/backend/executor/execCurrent.c
index 3523ac7ae903b6d7a38891f632cdd66850d5d7f9..f775092896d6f1a536564e6e994c58e000bea40d 100644
--- a/src/backend/executor/execCurrent.c
+++ b/src/backend/executor/execCurrent.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$PostgreSQL: pgsql/src/backend/executor/execCurrent.c,v 1.5 2008/01/01 19:45:49 momjian Exp $
+ *	$PostgreSQL: pgsql/src/backend/executor/execCurrent.c,v 1.6 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -150,8 +150,7 @@ fetch_param_value(ExprContext *econtext, int paramId)
 		{
 			Assert(prm->ptype == REFCURSOROID);
 			/* We know that refcursor uses text's I/O routines */
-			return DatumGetCString(DirectFunctionCall1(textout,
-													   prm->value));
+			return TextDatumGetCString(prm->value);
 		}
 	}
 
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 97d22dc2cd345e23f5317627b6d69331faff88fc..d142796815b20b35727c3574751a1864b7a9e7c7 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.227 2008/03/25 19:26:53 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.228 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3039,13 +3039,7 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
 	if (*isNull)
 		result = NULL;
 	else
-	{
-		int			len = buf.len + VARHDRSZ;
-
-		result = palloc(len);
-		SET_VARSIZE(result, len);
-		memcpy(VARDATA(result), buf.data, buf.len);
-	}
+		result = cstring_to_text_with_len(buf.data, buf.len);
 
 	pfree(buf.data);
 	return PointerGetDatum(result);
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index da6976b62f794041dcccd4417eb1a3bd992e86da..678b43927d7b6d50625b96344d86fca04b8465d0 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.121 2008/03/18 22:04:14 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.122 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -244,7 +244,7 @@ init_sql_fcache(FmgrInfo *finfo)
 						  &isNull);
 	if (isNull)
 		elog(ERROR, "null prosrc for function %u", foid);
-	fcache->src = DatumGetCString(DirectFunctionCall1(textout, tmp));
+	fcache->src = TextDatumGetCString(tmp);
 
 	/*
 	 * Parse and rewrite the queries in the function text.
@@ -777,7 +777,7 @@ sql_exec_error_callback(void *arg)
 							  &isnull);
 		if (isnull)
 			elog(ERROR, "null prosrc");
-		prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp));
+		prosrc = TextDatumGetCString(tmp);
 		errposition(0);
 		internalerrposition(syntaxerrposition);
 		internalerrquery(prosrc);
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 0fac11a53718cb66a74c2802d4ec6a2413b3550d..8ddcf8686990c0dd873fef3573007e0e424b6772 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -61,7 +61,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.156 2008/01/11 18:39:40 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.157 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1549,7 +1549,7 @@ GetAggInitVal(Datum textInitVal, Oid transtype)
 	Datum		initVal;
 
 	getTypeInputInfo(transtype, &typinput, &typioparam);
-	strInitVal = DatumGetCString(DirectFunctionCall1(textout, textInitVal));
+	strInitVal = TextDatumGetCString(textInitVal);
 	initVal = OidInputFunctionCall(typinput, strInitVal,
 								   typioparam, -1);
 	pfree(strInitVal);
diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c
index e2477a1dd14f22d9ccc41d5f7c62d5781a06d940..a7d746ae58cb62dcb44baf29303d2cf26adb9261 100644
--- a/src/backend/libpq/be-fsstubs.c
+++ b/src/backend/libpq/be-fsstubs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/libpq/be-fsstubs.c,v 1.88 2008/03/22 01:55:14 ishii Exp $
+ *	  $PostgreSQL: pgsql/src/backend/libpq/be-fsstubs.c,v 1.89 2008/03/25 22:42:43 tgl Exp $
  *
  * NOTES
  *	  This should be moved to a more appropriate place.  It is here
@@ -47,6 +47,7 @@
 #include "miscadmin.h"
 #include "storage/fd.h"
 #include "storage/large_object.h"
+#include "utils/builtins.h"
 #include "utils/memutils.h"
 
 
@@ -320,7 +321,7 @@ lowrite(PG_FUNCTION_ARGS)
 Datum
 lo_import(PG_FUNCTION_ARGS)
 {
-	text	   *filename = PG_GETARG_TEXT_P(0);
+	text	   *filename = PG_GETARG_TEXT_PP(0);
 
 	PG_RETURN_OID(lo_import_internal(filename, InvalidOid));
 }
@@ -332,7 +333,7 @@ lo_import(PG_FUNCTION_ARGS)
 Datum
 lo_import_with_oid(PG_FUNCTION_ARGS)
 {
-	text	   *filename = PG_GETARG_TEXT_P(0);
+	text	   *filename = PG_GETARG_TEXT_PP(0);
 	Oid		   oid = PG_GETARG_OID(1);
 
 	PG_RETURN_OID(lo_import_internal(filename, oid));
@@ -362,11 +363,7 @@ lo_import_internal(text *filename, Oid lobjOid)
 	/*
 	 * open the file to be read in
 	 */
-	nbytes = VARSIZE(filename) - VARHDRSZ;
-	if (nbytes >= MAXPGPATH)
-		nbytes = MAXPGPATH - 1;
-	memcpy(fnamebuf, VARDATA(filename), nbytes);
-	fnamebuf[nbytes] = '\0';
+	text_to_cstring_buffer(filename, fnamebuf, sizeof(fnamebuf));
 	fd = PathNameOpenFile(fnamebuf, O_RDONLY | PG_BINARY, 0666);
 	if (fd < 0)
 		ereport(ERROR,
@@ -410,7 +407,7 @@ Datum
 lo_export(PG_FUNCTION_ARGS)
 {
 	Oid			lobjId = PG_GETARG_OID(0);
-	text	   *filename = PG_GETARG_TEXT_P(1);
+	text	   *filename = PG_GETARG_TEXT_PP(1);
 	File		fd;
 	int			nbytes,
 				tmp;
@@ -441,11 +438,7 @@ lo_export(PG_FUNCTION_ARGS)
 	 * 022. This code used to drop it all the way to 0, but creating
 	 * world-writable export files doesn't seem wise.
 	 */
-	nbytes = VARSIZE(filename) - VARHDRSZ;
-	if (nbytes >= MAXPGPATH)
-		nbytes = MAXPGPATH - 1;
-	memcpy(fnamebuf, VARDATA(filename), nbytes);
-	fnamebuf[nbytes] = '\0';
+	text_to_cstring_buffer(filename, fnamebuf, sizeof(fnamebuf));
 	oumask = umask((mode_t) 0022);
 	fd = PathNameOpenFile(fnamebuf, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
 	umask(oumask);
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 8a2e808cc30813b537b9e715e4cbc9e62e137689..189793c2cc7a99ecb273c098afba3a7dbe663fbf 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.227 2008/02/07 17:53:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.228 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2711,8 +2711,7 @@ prefix_quals(Node *leftop, Oid opfamily,
 		switch (prefix_const->consttype)
 		{
 			case TEXTOID:
-				prefix = DatumGetCString(DirectFunctionCall1(textout,
-												  prefix_const->constvalue));
+				prefix = TextDatumGetCString(prefix_const->constvalue);
 				break;
 			case BYTEAOID:
 				prefix = DatumGetCString(DirectFunctionCall1(byteaout,
@@ -2868,15 +2867,15 @@ static Datum
 string_to_datum(const char *str, Oid datatype)
 {
 	/*
-	 * We cheat a little by assuming that textin() will do for bpchar and
-	 * varchar constants too...
+	 * We cheat a little by assuming that CStringGetTextDatum() will do for
+	 * bpchar and varchar constants too...
 	 */
 	if (datatype == NAMEOID)
 		return DirectFunctionCall1(namein, CStringGetDatum(str));
 	else if (datatype == BYTEAOID)
 		return DirectFunctionCall1(byteain, CStringGetDatum(str));
 	else
-		return DirectFunctionCall1(textin, CStringGetDatum(str));
+		return CStringGetTextDatum(str);
 }
 
 /*
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 818894886a560ee31ee1e5dac0cbdfdfda7890db..95e5077d38cd5d9a3081252a221a36ef27c38580 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.255 2008/03/18 22:04:14 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.256 2008/03/25 22:42:43 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -3002,7 +3002,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
 						  &isNull);
 	if (isNull)
 		elog(ERROR, "null prosrc for function %u", funcid);
-	src = DatumGetCString(DirectFunctionCall1(textout, tmp));
+	src = TextDatumGetCString(tmp);
 
 	/*
 	 * We just do parsing and parse analysis, not rewriting, because rewriting
@@ -3227,7 +3227,7 @@ sql_inline_error_callback(void *arg)
 							  &isnull);
 		if (isnull)
 			elog(ERROR, "null prosrc");
-		prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp));
+		prosrc = TextDatumGetCString(tmp);
 		errposition(0);
 		internalerrposition(syntaxerrposition);
 		internalerrquery(prosrc);
@@ -3454,7 +3454,7 @@ inline_set_returning_function(PlannerInfo *root, Node *node)
 						  &isNull);
 	if (isNull)
 		elog(ERROR, "null prosrc for function %u", fexpr->funcid);
-	src = DatumGetCString(DirectFunctionCall1(textout, tmp));
+	src = TextDatumGetCString(tmp);
 
 	/*
 	 * Parse, analyze, and rewrite (unlike inline_function(), we can't
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index e269959297032e718d446b887f082b84948c3c38..88fba239cdb710a6268b72caadc11529bf8270cf 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -19,7 +19,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.10 2008/03/21 22:10:56 tgl Exp $
+ *	$PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.11 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -811,7 +811,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
 	{
 		char	   *exprsString;
 
-		exprsString = DatumGetCString(DirectFunctionCall1(textout, datum));
+		exprsString = TextDatumGetCString(datum);
 		indexprs = (List *) stringToNode(exprsString);
 	}
 	else
@@ -904,7 +904,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
 		char	   *pred_str;
 
 		/* Convert text string to node tree */
-		pred_str = DatumGetCString(DirectFunctionCall1(textout, datum));
+		pred_str = TextDatumGetCString(datum);
 		index->whereClause = (Node *) stringToNode(pred_str);
 		/* Adjust attribute numbers */
 		change_varattnos_of_a_node(index->whereClause, attmap);
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 75a2e0b824b4a07ec5e7cfca13904154f0388eb4..c96512ef31c4b502fe134d6e6d2f5deb5844e7f9 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.124 2008/01/01 19:45:51 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.125 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -83,8 +83,8 @@ InsertRule(char *rulname,
 	values[i++] = CharGetDatum(evtype + '0');	/* ev_type */
 	values[i++] = CharGetDatum(RULE_FIRES_ON_ORIGIN);	/* ev_enabled */
 	values[i++] = BoolGetDatum(evinstead);		/* is_instead */
-	values[i++] = DirectFunctionCall1(textin, CStringGetDatum(evqual)); /* ev_qual */
-	values[i++] = DirectFunctionCall1(textin, CStringGetDatum(actiontree));		/* ev_action */
+	values[i++] = CStringGetTextDatum(evqual);	/* ev_qual */
+	values[i++] = CStringGetTextDatum(actiontree);		/* ev_action */
 
 	/*
 	 * Ready to store new pg_rewrite tuple
diff --git a/src/backend/tsearch/dict.c b/src/backend/tsearch/dict.c
index c17194f689ceb03775f13cdcfefd644439ac96bd..34b26528afa9ff2c28bfc1628d94994720457c97 100644
--- a/src/backend/tsearch/dict.c
+++ b/src/backend/tsearch/dict.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tsearch/dict.c,v 1.4 2008/01/01 19:45:52 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tsearch/dict.c,v 1.5 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,7 +64,7 @@ ts_lexize(PG_FUNCTION_ARGS)
 	ptr = res;
 	while (ptr->lexeme)
 	{
-		da[ptr - res] = DirectFunctionCall1(textin, CStringGetDatum(ptr->lexeme));
+		da[ptr - res] = CStringGetTextDatum(ptr->lexeme);
 		ptr++;
 	}
 
diff --git a/src/backend/tsearch/to_tsany.c b/src/backend/tsearch/to_tsany.c
index 5e1f82ba59ca8119e429d67c30def8b8903ea340..a217ff0c5bc935ba7c4f43671e526f068c0a265e 100644
--- a/src/backend/tsearch/to_tsany.c
+++ b/src/backend/tsearch/to_tsany.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tsearch/to_tsany.c,v 1.10 2008/03/07 14:30:20 teodor Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tsearch/to_tsany.c,v 1.11 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -337,7 +337,7 @@ to_tsquery_byid(PG_FUNCTION_ARGS)
 	QueryItem  *res;
 	int4		len;
 
-	query = parse_tsquery(TextPGetCString(in), pushval_morph, ObjectIdGetDatum(cfgid), false);
+	query = parse_tsquery(text_to_cstring(in), pushval_morph, ObjectIdGetDatum(cfgid), false);
 
 	if (query->size == 0)
 		PG_RETURN_TSQUERY(query);
@@ -387,7 +387,7 @@ plainto_tsquery_byid(PG_FUNCTION_ARGS)
 	QueryItem  *res;
 	int4		len;
 
-	query = parse_tsquery(TextPGetCString(in), pushval_morph, ObjectIdGetDatum(cfgid), true);
+	query = parse_tsquery(text_to_cstring(in), pushval_morph, ObjectIdGetDatum(cfgid), true);
 
 	if (query->size == 0)
 		PG_RETURN_TSQUERY(query);
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 65d7794b4e4944eb2ef590877e3ddc1f08479e96..3cf54e58750fd01ea73b6270626299bd79a21b42 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.139 2008/01/01 19:45:52 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.140 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1313,10 +1313,7 @@ makeaclitem(PG_FUNCTION_ARGS)
 static AclMode
 convert_priv_string(text *priv_type_text)
 {
-	char	   *priv_type;
-
-	priv_type = DatumGetCString(DirectFunctionCall1(textout,
-										   PointerGetDatum(priv_type_text)));
+	char	   *priv_type = text_to_cstring(priv_type_text);
 
 	if (pg_strcasecmp(priv_type, "SELECT") == 0)
 		return ACL_SELECT;
@@ -1526,10 +1523,7 @@ convert_table_name(text *tablename)
 static AclMode
 convert_table_priv_string(text *priv_type_text)
 {
-	char	   *priv_type;
-
-	priv_type = DatumGetCString(DirectFunctionCall1(textout,
-										   PointerGetDatum(priv_type_text)));
+	char	   *priv_type = text_to_cstring(priv_type_text);
 
 	/*
 	 * Return mode from priv_type string
@@ -1736,12 +1730,9 @@ has_database_privilege_id_id(PG_FUNCTION_ARGS)
 static Oid
 convert_database_name(text *databasename)
 {
-	char	   *dbname;
+	char	   *dbname = text_to_cstring(databasename);
 	Oid			oid;
 
-	dbname = DatumGetCString(DirectFunctionCall1(textout,
-											 PointerGetDatum(databasename)));
-
 	oid = get_database_oid(dbname);
 	if (!OidIsValid(oid))
 		ereport(ERROR,
@@ -1758,10 +1749,7 @@ convert_database_name(text *databasename)
 static AclMode
 convert_database_priv_string(text *priv_type_text)
 {
-	char	   *priv_type;
-
-	priv_type = DatumGetCString(DirectFunctionCall1(textout,
-										   PointerGetDatum(priv_type_text)));
+	char	   *priv_type = text_to_cstring(priv_type_text);
 
 	/*
 	 * Return mode from priv_type string
@@ -1953,12 +1941,9 @@ has_function_privilege_id_id(PG_FUNCTION_ARGS)
 static Oid
 convert_function_name(text *functionname)
 {
-	char	   *funcname;
+	char	   *funcname = text_to_cstring(functionname);
 	Oid			oid;
 
-	funcname = DatumGetCString(DirectFunctionCall1(textout,
-											 PointerGetDatum(functionname)));
-
 	oid = DatumGetObjectId(DirectFunctionCall1(regprocedurein,
 											   CStringGetDatum(funcname)));
 
@@ -1977,10 +1962,7 @@ convert_function_name(text *functionname)
 static AclMode
 convert_function_priv_string(text *priv_type_text)
 {
-	char	   *priv_type;
-
-	priv_type = DatumGetCString(DirectFunctionCall1(textout,
-										   PointerGetDatum(priv_type_text)));
+	char	   *priv_type = text_to_cstring(priv_type_text);
 
 	/*
 	 * Return mode from priv_type string
@@ -2157,12 +2139,9 @@ has_language_privilege_id_id(PG_FUNCTION_ARGS)
 static Oid
 convert_language_name(text *languagename)
 {
-	char	   *langname;
+	char	   *langname = text_to_cstring(languagename);
 	Oid			oid;
 
-	langname = DatumGetCString(DirectFunctionCall1(textout,
-											 PointerGetDatum(languagename)));
-
 	oid = GetSysCacheOid(LANGNAME,
 						 CStringGetDatum(langname),
 						 0, 0, 0);
@@ -2181,10 +2160,7 @@ convert_language_name(text *languagename)
 static AclMode
 convert_language_priv_string(text *priv_type_text)
 {
-	char	   *priv_type;
-
-	priv_type = DatumGetCString(DirectFunctionCall1(textout,
-										   PointerGetDatum(priv_type_text)));
+	char	   *priv_type = text_to_cstring(priv_type_text);
 
 	/*
 	 * Return mode from priv_type string
@@ -2361,12 +2337,9 @@ has_schema_privilege_id_id(PG_FUNCTION_ARGS)
 static Oid
 convert_schema_name(text *schemaname)
 {
-	char	   *nspname;
+	char	   *nspname = text_to_cstring(schemaname);
 	Oid			oid;
 
-	nspname = DatumGetCString(DirectFunctionCall1(textout,
-											   PointerGetDatum(schemaname)));
-
 	oid = GetSysCacheOid(NAMESPACENAME,
 						 CStringGetDatum(nspname),
 						 0, 0, 0);
@@ -2385,10 +2358,7 @@ convert_schema_name(text *schemaname)
 static AclMode
 convert_schema_priv_string(text *priv_type_text)
 {
-	char	   *priv_type;
-
-	priv_type = DatumGetCString(DirectFunctionCall1(textout,
-										   PointerGetDatum(priv_type_text)));
+	char	   *priv_type = text_to_cstring(priv_type_text);
 
 	/*
 	 * Return mode from priv_type string
@@ -2569,11 +2539,9 @@ has_tablespace_privilege_id_id(PG_FUNCTION_ARGS)
 static Oid
 convert_tablespace_name(text *tablespacename)
 {
-	char	   *spcname;
+	char	   *spcname = text_to_cstring(tablespacename);
 	Oid			oid;
 
-	spcname = DatumGetCString(DirectFunctionCall1(textout,
-										   PointerGetDatum(tablespacename)));
 	oid = get_tablespace_oid(spcname);
 
 	if (!OidIsValid(oid))
@@ -2591,10 +2559,7 @@ convert_tablespace_name(text *tablespacename)
 static AclMode
 convert_tablespace_priv_string(text *priv_type_text)
 {
-	char	   *priv_type;
-
-	priv_type = DatumGetCString(DirectFunctionCall1(textout,
-										   PointerGetDatum(priv_type_text)));
+	char	   *priv_type = text_to_cstring(priv_type_text);
 
 	/*
 	 * Return mode from priv_type string
@@ -2777,10 +2742,7 @@ pg_has_role_id_id(PG_FUNCTION_ARGS)
 static AclMode
 convert_role_priv_string(text *priv_type_text)
 {
-	char	   *priv_type;
-
-	priv_type = DatumGetCString(DirectFunctionCall1(textout,
-										   PointerGetDatum(priv_type_text)));
+	char	   *priv_type = text_to_cstring(priv_type_text);
 
 	/*
 	 * Return mode from priv_type string
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index b2beb18bc5f4413a992bf468c3625b67213e168c..f34ee3b773e84cf278b481dfdeed79548fee2c3c 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.141 2008/02/29 20:58:33 alvherre Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.142 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1533,39 +1533,33 @@ Datum
 array_dims(PG_FUNCTION_ARGS)
 {
 	ArrayType  *v = PG_GETARG_ARRAYTYPE_P(0);
-	text	   *result;
 	char	   *p;
-	int			nbytes,
-				i;
+	int			i;
 	int		   *dimv,
 			   *lb;
 
-	/* Sanity check: does it look like an array at all? */
-	if (ARR_NDIM(v) <= 0 || ARR_NDIM(v) > MAXDIM)
-		PG_RETURN_NULL();
-
-	nbytes = ARR_NDIM(v) * 33 + 1;
-
 	/*
 	 * 33 since we assume 15 digits per number + ':' +'[]'
 	 *
-	 * +1 allows for temp trailing null
+	 * +1 for trailing null
 	 */
+	char		buf[MAXDIM * 33 + 1];
 
-	result = (text *) palloc(nbytes + VARHDRSZ);
-	p = VARDATA(result);
+	/* Sanity check: does it look like an array at all? */
+	if (ARR_NDIM(v) <= 0 || ARR_NDIM(v) > MAXDIM)
+		PG_RETURN_NULL();
 
 	dimv = ARR_DIMS(v);
 	lb = ARR_LBOUND(v);
 
+	p = buf;
 	for (i = 0; i < ARR_NDIM(v); i++)
 	{
 		sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1);
 		p += strlen(p);
 	}
-	SET_VARSIZE(result, strlen(VARDATA(result)) + VARHDRSZ);
 
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(buf));
 }
 
 /*
diff --git a/src/backend/utils/adt/bool.c b/src/backend/utils/adt/bool.c
index 7261ab3e4069e9a4e3df1acc4d9f7478c71599de..4ba234c62c6eab068126b5f7a69e55c4eb18d152 100644
--- a/src/backend/utils/adt/bool.c
+++ b/src/backend/utils/adt/bool.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/bool.c,v 1.42 2008/01/01 19:45:52 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/bool.c,v 1.43 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -152,14 +152,14 @@ Datum
 booltext(PG_FUNCTION_ARGS)
 {
 	bool		arg1 = PG_GETARG_BOOL(0);
-	char	   *str;
+	const char *str;
 
 	if (arg1)
 		str = "true";
 	else
 		str = "false";
 
-	PG_RETURN_DATUM(DirectFunctionCall1(textin, CStringGetDatum(str)));
+	PG_RETURN_TEXT_P(cstring_to_text(str));
 }
 
 
diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c
index df5d7bf862915b4baf96dbb9825deba6b74d841c..84e8c742ec5f19354d6b1a4cff748fe8cac394bc 100644
--- a/src/backend/utils/adt/cash.c
+++ b/src/backend/utils/adt/cash.c
@@ -13,7 +13,7 @@
  * this version handles 64 bit numbers and so can hold values up to
  * $92,233,720,368,547,758.07.
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/cash.c,v 1.77 2007/11/24 16:18:48 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/cash.c,v 1.78 2008/03/25 22:42:43 tgl Exp $
  */
 
 #include "postgres.h"
@@ -24,6 +24,7 @@
 #include <locale.h>
 
 #include "libpq/pqformat.h"
+#include "utils/builtins.h"
 #include "utils/cash.h"
 #include "utils/pg_locale.h"
 
@@ -796,7 +797,6 @@ cash_words(PG_FUNCTION_ARGS)
 	Cash		m4;
 	Cash		m5;
 	Cash		m6;
-	text	   *result;
 
 	/* work with positive numbers */
 	if (value < 0)
@@ -862,10 +862,6 @@ cash_words(PG_FUNCTION_ARGS)
 	/* capitalize output */
 	buf[0] = pg_toupper((unsigned char) buf[0]);
 
-	/* make a text type for output */
-	result = (text *) palloc(strlen(buf) + VARHDRSZ);
-	SET_VARSIZE(result, strlen(buf) + VARHDRSZ);
-	memcpy(VARDATA(result), buf, strlen(buf));
-
-	PG_RETURN_TEXT_P(result);
+	/* return as text datum */
+	PG_RETURN_TEXT_P(cstring_to_text(buf));
 }
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 5b6b9ebfa979ef3300ebe56aced5a14b6d9374d4..e7374388dd16335a3c3615cd3feeed72554995b8 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.140 2008/03/21 01:31:42 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.141 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1594,15 +1594,15 @@ time_mi_interval(PG_FUNCTION_ARGS)
 Datum
 time_part(PG_FUNCTION_ARGS)
 {
-	text	   *units = PG_GETARG_TEXT_P(0);
+	text	   *units = PG_GETARG_TEXT_PP(0);
 	TimeADT		time = PG_GETARG_TIMEADT(1);
 	float8		result;
 	int			type,
 				val;
 	char	   *lowunits;
 
-	lowunits = downcase_truncate_identifier(VARDATA(units),
-											VARSIZE(units) - VARHDRSZ,
+	lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
+											VARSIZE_ANY_EXHDR(units),
 											false);
 
 	type = DecodeUnits(0, lowunits, &val);
@@ -1666,9 +1666,7 @@ time_part(PG_FUNCTION_ARGS)
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 						 errmsg("\"time\" units \"%s\" not recognized",
-								DatumGetCString(DirectFunctionCall1(textout,
-												 PointerGetDatum(units))))));
-
+								lowunits)));
 				result = 0;
 		}
 	}
@@ -1685,8 +1683,7 @@ time_part(PG_FUNCTION_ARGS)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("\"time\" units \"%s\" not recognized",
-						DatumGetCString(DirectFunctionCall1(textout,
-												 PointerGetDatum(units))))));
+						lowunits)));
 		result = 0;
 	}
 
@@ -2323,15 +2320,15 @@ datetimetz_timestamptz(PG_FUNCTION_ARGS)
 Datum
 timetz_part(PG_FUNCTION_ARGS)
 {
-	text	   *units = PG_GETARG_TEXT_P(0);
+	text	   *units = PG_GETARG_TEXT_PP(0);
 	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);
 	float8		result;
 	int			type,
 				val;
 	char	   *lowunits;
 
-	lowunits = downcase_truncate_identifier(VARDATA(units),
-											VARSIZE(units) - VARHDRSZ,
+	lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
+											VARSIZE_ANY_EXHDR(units),
 											false);
 
 	type = DecodeUnits(0, lowunits, &val);
@@ -2408,9 +2405,7 @@ timetz_part(PG_FUNCTION_ARGS)
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				errmsg("\"time with time zone\" units \"%s\" not recognized",
-					   DatumGetCString(DirectFunctionCall1(textout,
-												 PointerGetDatum(units))))));
-
+					   lowunits)));
 				result = 0;
 		}
 	}
@@ -2427,9 +2422,7 @@ timetz_part(PG_FUNCTION_ARGS)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("\"time with time zone\" units \"%s\" not recognized",
-						DatumGetCString(DirectFunctionCall1(textout,
-												 PointerGetDatum(units))))));
-
+						lowunits)));
 		result = 0;
 	}
 
@@ -2443,12 +2436,11 @@ timetz_part(PG_FUNCTION_ARGS)
 Datum
 timetz_zone(PG_FUNCTION_ARGS)
 {
-	text	   *zone = PG_GETARG_TEXT_P(0);
+	text	   *zone = PG_GETARG_TEXT_PP(0);
 	TimeTzADT  *t = PG_GETARG_TIMETZADT_P(1);
 	TimeTzADT  *result;
 	int			tz;
 	char		tzname[TZ_STRLEN_MAX + 1];
-	int			len;
 	pg_tz	   *tzp;
 
 	/*
@@ -2456,9 +2448,7 @@ timetz_zone(PG_FUNCTION_ARGS)
 	 * (to handle cases like "America/New_York"), and if that fails, we look
 	 * in the date token table (to handle cases like "EST").
 	 */
-	len = Min(VARSIZE(zone) - VARHDRSZ, TZ_STRLEN_MAX);
-	memcpy(tzname, VARDATA(zone), len);
-	tzname[len] = '\0';
+	text_to_cstring_buffer(zone, tzname, sizeof(tzname));
 	tzp = pg_tzset(tzname);
 	if (tzp)
 	{
@@ -2475,8 +2465,8 @@ timetz_zone(PG_FUNCTION_ARGS)
 		int			type,
 					val;
 
-		lowzone = downcase_truncate_identifier(VARDATA(zone),
-											   VARSIZE(zone) - VARHDRSZ,
+		lowzone = downcase_truncate_identifier(tzname,
+											   strlen(tzname),
 											   false);
 		type = DecodeSpecial(0, lowzone, &val);
 
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 08f21b46b0a1769536c740ef6c2fb5062aba8772..ef6a87d3a83222bd2dde7dc66a26eac07cae84cc 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.187 2008/02/25 23:36:28 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.188 2008/03/25 22:42:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3910,7 +3910,7 @@ pg_timezone_abbrevs(PG_FUNCTION_ARGS)
 	for (p = (unsigned char *) buffer; *p; p++)
 		*p = pg_toupper(*p);
 
-	values[0] = DirectFunctionCall1(textin, CStringGetDatum(buffer));
+	values[0] = CStringGetTextDatum(buffer);
 
 	MemSet(&tm, 0, sizeof(struct pg_tm));
 	tm.tm_min = (-1) * FROMVAL(&timezonetktbl[*pindex]);
@@ -4020,11 +4020,8 @@ pg_timezone_names(PG_FUNCTION_ARGS)
 
 	MemSet(nulls, 0, sizeof(nulls));
 
-	values[0] = DirectFunctionCall1(textin,
-								  CStringGetDatum(pg_get_timezone_name(tz)));
-
-	values[1] = DirectFunctionCall1(textin,
-									CStringGetDatum(tzn ? tzn : ""));
+	values[0] = CStringGetTextDatum(pg_get_timezone_name(tz));
+	values[1] = CStringGetTextDatum(tzn ? tzn : "");
 
 	MemSet(&itm, 0, sizeof(struct pg_tm));
 	itm.tm_sec = -tzoff;
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 00ac3b0e094796db118975f2c7f516b82eb3c758..72807321ae33b189b41c615fc4bbe9aa673a88ae 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2002-2008, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.16 2008/01/01 19:45:52 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.17 2008/03/25 22:42:44 tgl Exp $
  *
  */
 
@@ -393,41 +393,39 @@ Datum
 pg_size_pretty(PG_FUNCTION_ARGS)
 {
 	int64		size = PG_GETARG_INT64(0);
-	char	   *result = palloc(50 + VARHDRSZ);
+	char		buf[64];
 	int64		limit = 10 * 1024;
 	int64		mult = 1;
 
 	if (size < limit * mult)
-		snprintf(VARDATA(result), 50, INT64_FORMAT " bytes", size);
+		snprintf(buf, sizeof(buf), INT64_FORMAT " bytes", size);
 	else
 	{
 		mult *= 1024;
 		if (size < limit * mult)
-			snprintf(VARDATA(result), 50, INT64_FORMAT " kB",
+			snprintf(buf, sizeof(buf), INT64_FORMAT " kB",
 					 (size + mult / 2) / mult);
 		else
 		{
 			mult *= 1024;
 			if (size < limit * mult)
-				snprintf(VARDATA(result), 50, INT64_FORMAT " MB",
+				snprintf(buf, sizeof(buf), INT64_FORMAT " MB",
 						 (size + mult / 2) / mult);
 			else
 			{
 				mult *= 1024;
 				if (size < limit * mult)
-					snprintf(VARDATA(result), 50, INT64_FORMAT " GB",
+					snprintf(buf, sizeof(buf), INT64_FORMAT " GB",
 							 (size + mult / 2) / mult);
 				else
 				{
 					mult *= 1024;
-					snprintf(VARDATA(result), 50, INT64_FORMAT " TB",
+					snprintf(buf, sizeof(buf), INT64_FORMAT " TB",
 							 (size + mult / 2) / mult);
 				}
 			}
 		}
 	}
 
-	SET_VARSIZE(result, strlen(VARDATA(result)) + VARHDRSZ);
-
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(buf));
 }
diff --git a/src/backend/utils/adt/encode.c b/src/backend/utils/adt/encode.c
index cbbc4b69a2f1465ed7eff32d173607c40572f442..290888f996f7ea33cdee6bb778e930e035beaf59 100644
--- a/src/backend/utils/adt/encode.c
+++ b/src/backend/utils/adt/encode.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/encode.c,v 1.21 2008/02/26 02:54:08 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/encode.c,v 1.22 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,7 +46,7 @@ binary_encode(PG_FUNCTION_ARGS)
 
 	datalen = VARSIZE(data) - VARHDRSZ;
 
-	namebuf = DatumGetCString(DirectFunctionCall1(textout, name));
+	namebuf = TextDatumGetCString(name);
 
 	enc = pg_find_encoding(namebuf);
 	if (enc == NULL)
@@ -82,7 +82,7 @@ binary_decode(PG_FUNCTION_ARGS)
 
 	datalen = VARSIZE(data) - VARHDRSZ;
 
-	namebuf = DatumGetCString(DirectFunctionCall1(textout, name));
+	namebuf = TextDatumGetCString(name);
 
 	enc = pg_find_encoding(namebuf);
 	if (enc == NULL)
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index 86314e1a751ae058318c66de5b6c80cbb512b2bf..1ca2462c793d4407c0e354824d9da81ff3aeabb0 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.49 2008/01/01 19:45:52 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.50 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,7 +26,6 @@
 #include "mb/pg_wchar.h"
 
 #define MAX_INT32_LEN 11
-#define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str))
 
 static char *format_type_internal(Oid type_oid, int32 typemod,
 					 bool typemod_given, bool allow_invalid);
@@ -84,7 +83,7 @@ format_type(PG_FUNCTION_ARGS)
 		result = format_type_internal(type_oid, typemod, true, true);
 	}
 
-	PG_RETURN_DATUM(_textin(result));
+	PG_RETURN_TEXT_P(cstring_to_text(result));
 }
 
 /*
@@ -454,7 +453,7 @@ oidvectortypes(PG_FUNCTION_ARGS)
 		left -= slen;
 	}
 
-	PG_RETURN_DATUM(_textin(result));
+	PG_RETURN_TEXT_P(cstring_to_text(result));
 }
 
 
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index d1cc69a73227679e08d4ed2f644ad02c2204b8d1..103543817d278a8d39c94bd3be9f329b1841ed01 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------
  * formatting.c
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.138 2008/03/22 22:32:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.139 2008/03/25 22:42:44 tgl Exp $
  *
  *
  *	 Portions Copyright (c) 1999-2008, PostgreSQL Global Development Group
@@ -924,7 +924,7 @@ static int	seq_search(char *name, char **array, int type, int max, int *len);
 static void do_to_timestamp(text *date_txt, text *fmt,
 				struct pg_tm * tm, fsec_t *fsec);
 static char *fill_str(char *str, int c, int max);
-static FormatNode *NUM_cache(int len, NUMDesc *Num, char *pars_str, bool *shouldFree);
+static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree);
 static char *int_to_roman(int number);
 static void NUM_prepare_locale(NUMProc *Np);
 static char *get_last_relevant_decnum(char *num);
@@ -2709,16 +2709,14 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
 	char	   *fmt_str,
 			   *result;
 	bool		incache;
-	int			fmt_len = VARSIZE(fmt) - VARHDRSZ;
-	int			reslen;
+	int			fmt_len;
 	text	   *res;
 
 	/*
 	 * Convert fmt to C string
 	 */
-	fmt_str = (char *) palloc(fmt_len + 1);
-	memcpy(fmt_str, VARDATA(fmt), fmt_len);
-	*(fmt_str + fmt_len) = '\0';
+	fmt_str = text_to_cstring(fmt);
+	fmt_len = strlen(fmt_str);
 
 	/*
 	 * Allocate workspace for result as C string
@@ -2779,10 +2777,7 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
 	pfree(fmt_str);
 
 	/* convert C-string result to TEXT format */
-	reslen = strlen(result);
-	res = (text *) palloc(reslen + VARHDRSZ);
-	memcpy(VARDATA(res), result, reslen);
-	SET_VARSIZE(res, reslen + VARHDRSZ);
+	res = cstring_to_text(result);
 
 	pfree(result);
 	return res;
@@ -3135,18 +3130,15 @@ do_to_timestamp(text *date_txt, text *fmt,
 	ZERO_tm(tm);
 	*fsec = 0;
 
-	fmt_len = VARSIZE(fmt) - VARHDRSZ;
+	fmt_len = VARSIZE_ANY_EXHDR(fmt);
 
 	if (fmt_len)
 	{
-		int			date_len;
 		char	   *fmt_str;
 		char	   *date_str;
 		bool		incache;
 
-		fmt_str = (char *) palloc(fmt_len + 1);
-		memcpy(fmt_str, VARDATA(fmt), fmt_len);
-		*(fmt_str + fmt_len) = '\0';
+		fmt_str = text_to_cstring(fmt);
 
 		/*
 		 * Allocate new memory if format picture is bigger than static cache
@@ -3195,13 +3187,7 @@ do_to_timestamp(text *date_txt, text *fmt,
 		/* dump_node(format, fmt_len); */
 #endif
 
-		/*
-		 * Convert date to C string
-		 */
-		date_len = VARSIZE(date_txt) - VARHDRSZ;
-		date_str = (char *) palloc(date_len + 1);
-		memcpy(date_str, VARDATA(date_txt), date_len);
-		*(date_str + date_len) = '\0';
+		date_str = text_to_cstring(date_txt);
 
 		DCH_from_char(format, date_str, &tmfc);
 
@@ -3548,17 +3534,12 @@ NUM_cache_remove(NUMCacheEntry *ent)
  * ----------
  */
 static FormatNode *
-NUM_cache(int len, NUMDesc *Num, char *pars_str, bool *shouldFree)
+NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
 {
 	FormatNode *format = NULL;
 	char	   *str;
 
-	/*
-	 * Convert VARDATA() to string
-	 */
-	str = (char *) palloc(len + 1);
-	memcpy(str, pars_str, len);
-	*(str + len) = '\0';
+	str = text_to_cstring(pars_str);
 
 	/*
 	 * Allocate new memory if format picture is bigger than static cache and
@@ -4597,11 +4578,11 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
  */
 #define NUM_TOCHAR_prepare \
 do { \
-	len = VARSIZE(fmt) - VARHDRSZ;					\
+	len = VARSIZE_ANY_EXHDR(fmt); \
 	if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ)		\
-		return DirectFunctionCall1(textin, CStringGetDatum(""));	\
+		PG_RETURN_TEXT_P(cstring_to_text("")); \
 	result	= (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ);	\
-	format	= NUM_cache(len, &Num, VARDATA(fmt), &shouldFree);		\
+	format	= NUM_cache(len, &Num, fmt, &shouldFree);		\
 } while (0)
 
 /* ----------
@@ -4647,7 +4628,7 @@ numeric_to_number(PG_FUNCTION_ARGS)
 	if (len <= 0 || len >= INT_MAX / NUM_MAX_ITEM_SIZ)
 		PG_RETURN_NULL();
 
-	format = NUM_cache(len, &Num, VARDATA(fmt), &shouldFree);
+	format = NUM_cache(len, &Num, fmt, &shouldFree);
 
 	numstr = (char *) palloc((len * NUM_MAX_ITEM_SIZ) + 1);
 
diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index a3a16bcfa50c488230ad71302b3103be52496fad..86408859f22c0982adeedae24eb139954145c2a4 100644
--- a/src/backend/utils/adt/genfile.c
+++ b/src/backend/utils/adt/genfile.c
@@ -9,7 +9,7 @@
  * Author: Andreas Pflug <pgadmin@pse-consulting.de>
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/genfile.c,v 1.17 2008/01/01 19:45:52 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/genfile.c,v 1.18 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,12 +46,9 @@ typedef struct
 static char *
 convert_and_check_filename(text *arg)
 {
-	int			input_len = VARSIZE(arg) - VARHDRSZ;
-	char	   *filename = palloc(input_len + 1);
-
-	memcpy(filename, VARDATA(arg), input_len);
-	filename[input_len] = '\0';
+	char	   *filename;
 
+	filename = text_to_cstring(arg);
 	canonicalize_path(filename);	/* filename can change length here */
 
 	/* Disallow ".." in the path */
@@ -253,18 +250,11 @@ pg_ls_dir(PG_FUNCTION_ARGS)
 
 	while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
 	{
-		int			len = strlen(de->d_name);
-		text	   *result;
-
 		if (strcmp(de->d_name, ".") == 0 ||
 			strcmp(de->d_name, "..") == 0)
 			continue;
 
-		result = palloc(len + VARHDRSZ);
-		SET_VARSIZE(result, len + VARHDRSZ);
-		memcpy(VARDATA(result), de->d_name, len);
-
-		SRF_RETURN_NEXT(funcctx, PointerGetDatum(result));
+		SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(de->d_name));
 	}
 
 	FreeDir(fctx->dirdesc);
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index de5420e7719803116484c439e3632f290d942fd0..55a6adaa5fa91261bc3c53caa9b374562477075b 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -6,7 +6,7 @@
  * Copyright (c) 2002-2008, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *		$PostgreSQL: pgsql/src/backend/utils/adt/lockfuncs.c,v 1.32 2008/01/08 23:18:51 tgl Exp $
+ *		$PostgreSQL: pgsql/src/backend/utils/adt/lockfuncs.c,v 1.33 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -57,7 +57,7 @@ VXIDGetDatum(BackendId bid, LocalTransactionId lxid)
 
 	snprintf(vxidstr, sizeof(vxidstr), "%d/%u", bid, lxid);
 
-	return DirectFunctionCall1(textin, CStringGetDatum(vxidstr));
+	return CStringGetTextDatum(vxidstr);
 }
 
 
@@ -214,8 +214,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
 					 (int) lock->tag.locktag_type);
 			locktypename = tnbuf;
 		}
-		values[0] = DirectFunctionCall1(textin,
-										CStringGetDatum(locktypename));
+		values[0] = CStringGetTextDatum(locktypename);
 
 		switch ((LockTagType) lock->tag.locktag_type)
 		{
@@ -297,9 +296,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
 			values[11] = Int32GetDatum(proc->pid);
 		else
 			nulls[11] = 'n';
-		values[12] = DirectFunctionCall1(textin,
-					  CStringGetDatum(GetLockmodeName(LOCK_LOCKMETHOD(*lock),
-													  mode)));
+		values[12] = CStringGetTextDatum(GetLockmodeName(LOCK_LOCKMETHOD(*lock), mode));
 		values[13] = BoolGetDatum(granted);
 
 		tuple = heap_formtuple(funcctx->tuple_desc, values, nulls);
diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c
index c1a484d9bb67b8790eb6567767542f05894f322b..a40ca5edd05b485faba9ae9e8bb2b0df93243807 100644
--- a/src/backend/utils/adt/nabstime.c
+++ b/src/backend/utils/adt/nabstime.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/nabstime.c,v 1.154 2008/03/21 01:31:42 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/nabstime.c,v 1.155 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1576,8 +1576,6 @@ timeofday(PG_FUNCTION_ARGS)
 	struct timeval tp;
 	char		templ[128];
 	char		buf[128];
-	text	   *result;
-	int			len;
 	pg_time_t	tt;
 
 	gettimeofday(&tp, NULL);
@@ -1586,9 +1584,5 @@ timeofday(PG_FUNCTION_ARGS)
 				pg_localtime(&tt, session_timezone));
 	snprintf(buf, sizeof(buf), templ, tp.tv_usec);
 
-	len = VARHDRSZ + strlen(buf);
-	result = (text *) palloc(len);
-	SET_VARSIZE(result, len);
-	memcpy(VARDATA(result), buf, len - VARHDRSZ);
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(buf));
 }
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index 7eb6ffe306f78a1200a765fb3c603890d0d650d5..8e58374e9b11df9c07adb596f821bd665b095082 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -1,7 +1,7 @@
 /*
  *	PostgreSQL type definitions for the INET and CIDR types.
  *
- *	$PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.72 2007/11/15 21:14:39 momjian Exp $
+ *	$PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.73 2008/03/25 22:42:44 tgl Exp $
  *
  *	Jon Postel RIP 16 Oct 1998
  */
@@ -601,8 +601,6 @@ Datum
 network_host(PG_FUNCTION_ARGS)
 {
 	inet	   *ip = PG_GETARG_INET_P(0);
-	text	   *ret;
-	int			len;
 	char	   *ptr;
 	char		tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
 
@@ -617,12 +615,7 @@ network_host(PG_FUNCTION_ARGS)
 	if ((ptr = strchr(tmp, '/')) != NULL)
 		*ptr = '\0';
 
-	/* Return string as a text datum */
-	len = strlen(tmp);
-	ret = (text *) palloc(len + VARHDRSZ);
-	SET_VARSIZE(ret, len + VARHDRSZ);
-	memcpy(VARDATA(ret), tmp, len);
-	PG_RETURN_TEXT_P(ret);
+	PG_RETURN_TEXT_P(cstring_to_text(tmp));
 }
 
 /*
@@ -634,7 +627,6 @@ Datum
 network_show(PG_FUNCTION_ARGS)
 {
 	inet	   *ip = PG_GETARG_INET_P(0);
-	text	   *ret;
 	int			len;
 	char		tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
 
@@ -651,21 +643,14 @@ network_show(PG_FUNCTION_ARGS)
 		snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
 	}
 
-	/* Return string as a text datum */
-	len = strlen(tmp);
-	ret = (text *) palloc(len + VARHDRSZ);
-	SET_VARSIZE(ret, len + VARHDRSZ);
-	memcpy(VARDATA(ret), tmp, len);
-	PG_RETURN_TEXT_P(ret);
+	PG_RETURN_TEXT_P(cstring_to_text(tmp));
 }
 
 Datum
 inet_abbrev(PG_FUNCTION_ARGS)
 {
 	inet	   *ip = PG_GETARG_INET_P(0);
-	text	   *ret;
 	char	   *dst;
-	int			len;
 	char		tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
 
 	dst = inet_net_ntop(ip_family(ip), ip_addr(ip),
@@ -676,21 +661,14 @@ inet_abbrev(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
 				 errmsg("could not format inet value: %m")));
 
-	/* Return string as a text datum */
-	len = strlen(tmp);
-	ret = (text *) palloc(len + VARHDRSZ);
-	SET_VARSIZE(ret, len + VARHDRSZ);
-	memcpy(VARDATA(ret), tmp, len);
-	PG_RETURN_TEXT_P(ret);
+	PG_RETURN_TEXT_P(cstring_to_text(tmp));
 }
 
 Datum
 cidr_abbrev(PG_FUNCTION_ARGS)
 {
 	inet	   *ip = PG_GETARG_INET_P(0);
-	text	   *ret;
 	char	   *dst;
-	int			len;
 	char		tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
 
 	dst = inet_cidr_ntop(ip_family(ip), ip_addr(ip),
@@ -701,12 +679,7 @@ cidr_abbrev(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
 				 errmsg("could not format cidr value: %m")));
 
-	/* Return string as a text datum */
-	len = strlen(tmp);
-	ret = (text *) palloc(len + VARHDRSZ);
-	SET_VARSIZE(ret, len + VARHDRSZ);
-	memcpy(VARDATA(ret), tmp, len);
-	PG_RETURN_TEXT_P(ret);
+	PG_RETURN_TEXT_P(cstring_to_text(tmp));
 }
 
 Datum
diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c
index 588cf5941dbdf90cf3fc52b9fdd920b61963fab1..257f60a8bbf14dd891a149c79b5cdcc41f5112a1 100644
--- a/src/backend/utils/adt/oracle_compat.c
+++ b/src/backend/utils/adt/oracle_compat.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	$PostgreSQL: pgsql/src/backend/utils/adt/oracle_compat.c,v 1.77 2008/01/01 19:45:52 momjian Exp $
+ *	$PostgreSQL: pgsql/src/backend/utils/adt/oracle_compat.c,v 1.78 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -76,9 +76,7 @@ texttowcs(const text *txt)
 				 errmsg("out of memory")));
 
 	/* Need a null-terminated version of the input */
-	workstr = (char *) palloc(nbytes + 1);
-	memcpy(workstr, VARDATA_ANY(txt), nbytes);
-	workstr[nbytes] = '\0';
+	workstr = text_to_cstring(txt);
 
 	/* Output workspace cannot have more codes than input bytes */
 	result = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
@@ -275,25 +273,16 @@ wstring_upper(char *str)
 	text	   *in_text;
 	text	   *out_text;
 	char	   *result;
-	int			nbytes = strlen(str);
 	int			i;
 
-	in_text = palloc(nbytes + VARHDRSZ);
-	memcpy(VARDATA(in_text), str, nbytes);
-	SET_VARSIZE(in_text, nbytes + VARHDRSZ);
-
+	in_text = cstring_to_text(str);
 	workspace = texttowcs(in_text);
 
 	for (i = 0; workspace[i] != 0; i++)
 		workspace[i] = towupper(workspace[i]);
 
 	out_text = wcstotext(workspace, i);
-
-	nbytes = VARSIZE(out_text) - VARHDRSZ;
-	result = palloc(nbytes + 1);
-	memcpy(result, VARDATA(out_text), nbytes);
-
-	result[nbytes] = '\0';
+	result = text_to_cstring(out_text);
 
 	pfree(workspace);
 	pfree(in_text);
@@ -309,25 +298,16 @@ wstring_lower(char *str)
 	text	   *in_text;
 	text	   *out_text;
 	char	   *result;
-	int			nbytes = strlen(str);
 	int			i;
 
-	in_text = palloc(nbytes + VARHDRSZ);
-	memcpy(VARDATA(in_text), str, nbytes);
-	SET_VARSIZE(in_text, nbytes + VARHDRSZ);
-
+	in_text = cstring_to_text(str);
 	workspace = texttowcs(in_text);
 
 	for (i = 0; workspace[i] != 0; i++)
 		workspace[i] = towlower(workspace[i]);
 
 	out_text = wcstotext(workspace, i);
-
-	nbytes = VARSIZE(out_text) - VARHDRSZ;
-	result = palloc(nbytes + 1);
-	memcpy(result, VARDATA(out_text), nbytes);
-
-	result[nbytes] = '\0';
+	result = text_to_cstring(out_text);
 
 	pfree(workspace);
 	pfree(in_text);
@@ -801,7 +781,6 @@ dotrim(const char *string, int stringlen,
 	   const char *set, int setlen,
 	   bool doltrim, bool dortrim)
 {
-	text	   *result;
 	int			i;
 
 	/* Nothing to do if either string or set is empty */
@@ -947,11 +926,7 @@ dotrim(const char *string, int stringlen,
 	}
 
 	/* Return selected portion of string */
-	result = (text *) palloc(VARHDRSZ + stringlen);
-	SET_VARSIZE(result, VARHDRSZ + stringlen);
-	memcpy(VARDATA(result), string, stringlen);
-
-	return result;
+	return cstring_to_text_with_len(string, stringlen);
 }
 
 /********************************************************************
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 7fb2d5951ee58d8b4ee8a3fc603d3698ed15f02c..f4c047b7edabc35d67711eb66c506fb699cb71d0 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.48 2008/01/01 19:45:52 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.49 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -414,9 +414,7 @@ Datum
 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
 {
 	int32		beid = PG_GETARG_INT32(0);
-	text	   *result;
 	PgBackendStatus *beentry;
-	int			len;
 	const char *activity;
 
 	if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
@@ -428,12 +426,7 @@ pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
 	else
 		activity = beentry->st_activity;
 
-	len = strlen(activity);
-	result = palloc(VARHDRSZ + len);
-	SET_VARSIZE(result, VARHDRSZ + len);
-	memcpy(VARDATA(result), activity, len);
-
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(activity));
 }
 
 
diff --git a/src/backend/utils/adt/quote.c b/src/backend/utils/adt/quote.c
index 519c6d874b5dec645cdb206df055314a3493cc51..6074414c372eb5384b55b2535a4a5edb5d804dc4 100644
--- a/src/backend/utils/adt/quote.c
+++ b/src/backend/utils/adt/quote.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.24 2008/03/23 00:24:19 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.25 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,26 +23,13 @@
 Datum
 quote_ident(PG_FUNCTION_ARGS)
 {
-	text	   *t = PG_GETARG_TEXT_P(0);
-	text	   *result;
+	text	   *t = PG_GETARG_TEXT_PP(0);
 	const char *qstr;
 	char	   *str;
-	int			len;
-
-	/* We have to convert to a C string to use quote_identifier */
-	len = VARSIZE(t) - VARHDRSZ;
-	str = (char *) palloc(len + 1);
-	memcpy(str, VARDATA(t), len);
-	str[len] = '\0';
 
+	str = text_to_cstring(t);
 	qstr = quote_identifier(str);
-
-	len = strlen(qstr);
-	result = (text *) palloc(len + VARHDRSZ);
-	SET_VARSIZE(result, len + VARHDRSZ);
-	memcpy(VARDATA(result), qstr, len);
-
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(qstr));
 }
 
 /*
@@ -106,8 +93,7 @@ Datum
 quote_nullable(PG_FUNCTION_ARGS)
 {
 	if (PG_ARGISNULL(0))
-		PG_RETURN_DATUM(DirectFunctionCall1(textin,
-											CStringGetDatum("NULL")));
+		PG_RETURN_TEXT_P(cstring_to_text("NULL"));
 	else
 		PG_RETURN_DATUM(DirectFunctionCall1(quote_literal,
 											PG_GETARG_DATUM(0)));
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index db86d69efe5fa29379ee163df838dc11baf67c19..940cfc2b23de7d68f8fafd58e7171a6ab026022d 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.269 2008/01/06 01:03:16 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.270 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -697,8 +697,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
 		exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
 									 Anum_pg_index_indexprs, &isnull);
 		Assert(!isnull);
-		exprsString = DatumGetCString(DirectFunctionCall1(textout,
-														  exprsDatum));
+		exprsString = TextDatumGetCString(exprsDatum);
 		indexprs = (List *) stringToNode(exprsString);
 		pfree(exprsString);
 	}
@@ -836,8 +835,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
 			predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
 										Anum_pg_index_indpred, &isnull);
 			Assert(!isnull);
-			predString = DatumGetCString(DirectFunctionCall1(textout,
-															 predDatum));
+			predString = TextDatumGetCString(predDatum);
 			node = (Node *) stringToNode(predString);
 			pfree(predString);
 
@@ -1092,7 +1090,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
 					elog(ERROR, "null conbin for constraint %u",
 						 constraintId);
 
-				conbin = DatumGetCString(DirectFunctionCall1(textout, val));
+				conbin = TextDatumGetCString(val);
 				expr = stringToNode(conbin);
 
 				/* Set up deparsing context for Var nodes in constraint */
@@ -1222,8 +1220,7 @@ pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
 	char	   *str;
 
 	/* Convert input TEXT object to C string */
-	exprstr = DatumGetCString(DirectFunctionCall1(textout,
-												  PointerGetDatum(expr)));
+	exprstr = text_to_cstring(expr);
 
 	/* Convert expression to node tree */
 	node = (Node *) stringToNode(exprstr);
@@ -1233,6 +1230,8 @@ pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
 	str = deparse_expression_pretty(node, context, false, false,
 									prettyFlags, 0);
 
+	pfree(exprstr);
+
 	return str;
 }
 
@@ -1286,7 +1285,7 @@ Datum
 pg_get_serial_sequence(PG_FUNCTION_ARGS)
 {
 	text	   *tablename = PG_GETARG_TEXT_P(0);
-	text	   *columnname = PG_GETARG_TEXT_P(1);
+	text	   *columnname = PG_GETARG_TEXT_PP(1);
 	RangeVar   *tablerv;
 	Oid			tableOid;
 	char	   *column;
@@ -1302,8 +1301,7 @@ pg_get_serial_sequence(PG_FUNCTION_ARGS)
 	tableOid = RangeVarGetRelid(tablerv, false);
 
 	/* Get the number of the column */
-	column = DatumGetCString(DirectFunctionCall1(textout,
-											   PointerGetDatum(columnname)));
+	column = text_to_cstring(columnname);
 
 	attnum = get_attnum(tableOid, column);
 	if (attnum == InvalidAttrNumber)
@@ -5439,16 +5437,9 @@ static text *
 string_to_text(char *str)
 {
 	text	   *result;
-	int			slen = strlen(str);
-	int			tlen;
-
-	tlen = slen + VARHDRSZ;
-	result = (text *) palloc(tlen);
-	SET_VARSIZE(result, tlen);
-	memcpy(VARDATA(result), str, slen);
 
+	result = cstring_to_text(str);
 	pfree(str);
-
 	return result;
 }
 
@@ -5482,9 +5473,9 @@ flatten_reloptions(Oid relid)
 		 * array_to_text() relies on flinfo to be valid.  So use
 		 * OidFunctionCall2.
 		 */
-		sep = DirectFunctionCall1(textin, CStringGetDatum(", "));
+		sep = CStringGetTextDatum(", ");
 		txt = OidFunctionCall2(F_ARRAY_TO_TEXT, reloptions, sep);
-		result = DatumGetCString(DirectFunctionCall1(textout, txt));
+		result = TextDatumGetCString(txt);
 	}
 
 	ReleaseSysCache(tuple);
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index b6f1026375f884f1d21e6ce1e04b746080342054..68ce6acb52893fe0d2e294f5bdcee358cf3af2b0 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.246 2008/03/17 17:13:54 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.247 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1089,8 +1089,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
 		switch (prefix->consttype)
 		{
 			case TEXTOID:
-				prefixstr = DatumGetCString(DirectFunctionCall1(textout,
-														prefix->constvalue));
+				prefixstr = TextDatumGetCString(prefix->constvalue);
 				break;
 			case BYTEAOID:
 				prefixstr = DatumGetCString(DirectFunctionCall1(byteaout,
@@ -3339,15 +3338,8 @@ convert_string_datum(Datum value, Oid typid)
 		case BPCHAROID:
 		case VARCHAROID:
 		case TEXTOID:
-			{
-				char	   *str = (char *) VARDATA(DatumGetPointer(value));
-				int			strlength = VARSIZE(DatumGetPointer(value)) - VARHDRSZ;
-
-				val = (char *) palloc(strlength + 1);
-				memcpy(val, str, strlength);
-				val[strlength] = '\0';
-				break;
-			}
+			val = TextDatumGetCString(value);
+			break;
 		case NAMEOID:
 			{
 				NameData   *nm = (NameData *) DatumGetPointer(value);
@@ -4177,7 +4169,7 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive,
 
 	if (typeid != BYTEAOID)
 	{
-		patt = DatumGetCString(DirectFunctionCall1(textout, patt_const->constvalue));
+		patt = TextDatumGetCString(patt_const->constvalue);
 		pattlen = strlen(patt);
 	}
 	else
@@ -4282,7 +4274,7 @@ regex_fixed_prefix(Const *patt_const, bool case_insensitive,
 		 errmsg("regular-expression matching not supported on type bytea")));
 
 	/* the right-hand const is type text for all of these */
-	patt = DatumGetCString(DirectFunctionCall1(textout, patt_const->constvalue));
+	patt = TextDatumGetCString(patt_const->constvalue);
 
 	/*
 	 * Check for ARE director prefix.  It's worth our trouble to recognize
@@ -4618,7 +4610,7 @@ like_selectivity(Const *patt_const, bool case_insensitive)
 
 	if (typeid != BYTEAOID)
 	{
-		patt = DatumGetCString(DirectFunctionCall1(textout, patt_const->constvalue));
+		patt = TextDatumGetCString(patt_const->constvalue);
 		pattlen = strlen(patt);
 	}
 	else
@@ -4777,7 +4769,7 @@ regex_selectivity(Const *patt_const, bool case_insensitive)
 		 errmsg("regular-expression matching not supported on type bytea")));
 
 	/* the right-hand const is type text for all of these */
-	patt = DatumGetCString(DirectFunctionCall1(textout, patt_const->constvalue));
+	patt = TextDatumGetCString(patt_const->constvalue);
 	pattlen = strlen(patt);
 
 	/* If patt doesn't end with $, consider it to have a trailing wildcard */
@@ -4892,8 +4884,7 @@ make_greater_string(const Const *str_const, FmgrInfo *ltproc)
 	}
 	else
 	{
-		workstr = DatumGetCString(DirectFunctionCall1(textout,
-													  str_const->constvalue));
+		workstr = TextDatumGetCString(str_const->constvalue);
 		len = strlen(workstr);
 		if (lc_collate_is_c() || len == 0)
 			cmpstr = str_const->constvalue;
@@ -5000,15 +4991,15 @@ string_to_datum(const char *str, Oid datatype)
 	Assert(str != NULL);
 
 	/*
-	 * We cheat a little by assuming that textin() will do for bpchar and
-	 * varchar constants too...
+	 * We cheat a little by assuming that CStringGetTextDatum() will do for
+	 * bpchar and varchar constants too...
 	 */
 	if (datatype == NAMEOID)
 		return DirectFunctionCall1(namein, CStringGetDatum(str));
 	else if (datatype == BYTEAOID)
 		return DirectFunctionCall1(byteain, CStringGetDatum(str));
 	else
-		return DirectFunctionCall1(textin, CStringGetDatum(str));
+		return CStringGetTextDatum(str);
 }
 
 /*
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 8ca6f998c9811d1b3378436bbef18a0f2ce043a1..8a0f37292dc396eadaa8e48e6ccddc707ba66a32 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.186 2008/03/21 01:31:42 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.187 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3242,7 +3242,7 @@ timestamptz_age(PG_FUNCTION_ARGS)
 Datum
 timestamp_trunc(PG_FUNCTION_ARGS)
 {
-	text	   *units = PG_GETARG_TEXT_P(0);
+	text	   *units = PG_GETARG_TEXT_PP(0);
 	Timestamp	timestamp = PG_GETARG_TIMESTAMP(1);
 	Timestamp	result;
 	int			type,
@@ -3255,8 +3255,8 @@ timestamp_trunc(PG_FUNCTION_ARGS)
 	if (TIMESTAMP_NOT_FINITE(timestamp))
 		PG_RETURN_TIMESTAMP(timestamp);
 
-	lowunits = downcase_truncate_identifier(VARDATA(units),
-											VARSIZE(units) - VARHDRSZ,
+	lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
+											VARSIZE_ANY_EXHDR(units),
 											false);
 
 	type = DecodeUnits(0, lowunits, &val);
@@ -3374,7 +3374,7 @@ timestamp_trunc(PG_FUNCTION_ARGS)
 Datum
 timestamptz_trunc(PG_FUNCTION_ARGS)
 {
-	text	   *units = PG_GETARG_TEXT_P(0);
+	text	   *units = PG_GETARG_TEXT_PP(0);
 	TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(1);
 	TimestampTz result;
 	int			tz;
@@ -3390,8 +3390,8 @@ timestamptz_trunc(PG_FUNCTION_ARGS)
 	if (TIMESTAMP_NOT_FINITE(timestamp))
 		PG_RETURN_TIMESTAMPTZ(timestamp);
 
-	lowunits = downcase_truncate_identifier(VARDATA(units),
-											VARSIZE(units) - VARHDRSZ,
+	lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
+											VARSIZE_ANY_EXHDR(units),
 											false);
 
 	type = DecodeUnits(0, lowunits, &val);
@@ -3532,7 +3532,7 @@ timestamptz_trunc(PG_FUNCTION_ARGS)
 Datum
 interval_trunc(PG_FUNCTION_ARGS)
 {
-	text	   *units = PG_GETARG_TEXT_P(0);
+	text	   *units = PG_GETARG_TEXT_PP(0);
 	Interval   *interval = PG_GETARG_INTERVAL_P(1);
 	Interval   *result;
 	int			type,
@@ -3544,8 +3544,8 @@ interval_trunc(PG_FUNCTION_ARGS)
 
 	result = (Interval *) palloc(sizeof(Interval));
 
-	lowunits = downcase_truncate_identifier(VARDATA(units),
-											VARSIZE(units) - VARHDRSZ,
+	lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
+											VARSIZE_ANY_EXHDR(units),
 											false);
 
 	type = DecodeUnits(0, lowunits, &val);
@@ -3615,9 +3615,7 @@ interval_trunc(PG_FUNCTION_ARGS)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("interval units \"%s\" not recognized",
-						DatumGetCString(DirectFunctionCall1(textout,
-												 PointerGetDatum(units))))));
-		*result = *interval;
+						lowunits)));
 	}
 
 	PG_RETURN_INTERVAL_P(result);
@@ -3803,7 +3801,7 @@ date2isoyearday(int year, int mon, int mday)
 Datum
 timestamp_part(PG_FUNCTION_ARGS)
 {
-	text	   *units = PG_GETARG_TEXT_P(0);
+	text	   *units = PG_GETARG_TEXT_PP(0);
 	Timestamp	timestamp = PG_GETARG_TIMESTAMP(1);
 	float8		result;
 	int			type,
@@ -3819,8 +3817,8 @@ timestamp_part(PG_FUNCTION_ARGS)
 		PG_RETURN_FLOAT8(result);
 	}
 
-	lowunits = downcase_truncate_identifier(VARDATA(units),
-											VARSIZE(units) - VARHDRSZ,
+	lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
+											VARSIZE_ANY_EXHDR(units),
 											false);
 
 	type = DecodeUnits(0, lowunits, &val);
@@ -4031,7 +4029,7 @@ timestamp_part(PG_FUNCTION_ARGS)
 Datum
 timestamptz_part(PG_FUNCTION_ARGS)
 {
-	text	   *units = PG_GETARG_TEXT_P(0);
+	text	   *units = PG_GETARG_TEXT_PP(0);
 	TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(1);
 	float8		result;
 	int			tz;
@@ -4050,8 +4048,8 @@ timestamptz_part(PG_FUNCTION_ARGS)
 		PG_RETURN_FLOAT8(result);
 	}
 
-	lowunits = downcase_truncate_identifier(VARDATA(units),
-											VARSIZE(units) - VARHDRSZ,
+	lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
+											VARSIZE_ANY_EXHDR(units),
 											false);
 
 	type = DecodeUnits(0, lowunits, &val);
@@ -4246,7 +4244,7 @@ timestamptz_part(PG_FUNCTION_ARGS)
 Datum
 interval_part(PG_FUNCTION_ARGS)
 {
-	text	   *units = PG_GETARG_TEXT_P(0);
+	text	   *units = PG_GETARG_TEXT_PP(0);
 	Interval   *interval = PG_GETARG_INTERVAL_P(1);
 	float8		result;
 	int			type,
@@ -4256,8 +4254,8 @@ interval_part(PG_FUNCTION_ARGS)
 	struct pg_tm tt,
 			   *tm = &tt;
 
-	lowunits = downcase_truncate_identifier(VARDATA(units),
-											VARSIZE(units) - VARHDRSZ,
+	lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
+											VARSIZE_ANY_EXHDR(units),
 											false);
 
 	type = DecodeUnits(0, lowunits, &val);
@@ -4337,8 +4335,7 @@ interval_part(PG_FUNCTION_ARGS)
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("interval units \"%s\" not supported",
-								 DatumGetCString(DirectFunctionCall1(textout,
-												 PointerGetDatum(units))))));
+									lowunits)));
 					result = 0;
 			}
 
@@ -4365,8 +4362,7 @@ interval_part(PG_FUNCTION_ARGS)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("interval units \"%s\" not recognized",
-						DatumGetCString(DirectFunctionCall1(textout,
-												 PointerGetDatum(units))))));
+						lowunits)));
 		result = 0;
 	}
 
@@ -4385,13 +4381,12 @@ interval_part(PG_FUNCTION_ARGS)
 Datum
 timestamp_zone(PG_FUNCTION_ARGS)
 {
-	text	   *zone = PG_GETARG_TEXT_P(0);
+	text	   *zone = PG_GETARG_TEXT_PP(0);
 	Timestamp	timestamp = PG_GETARG_TIMESTAMP(1);
 	TimestampTz result;
 	int			tz;
 	pg_tz	   *tzp;
 	char		tzname[TZ_STRLEN_MAX + 1];
-	int			len;
 
 	if (TIMESTAMP_NOT_FINITE(timestamp))
 		PG_RETURN_TIMESTAMPTZ(timestamp);
@@ -4401,9 +4396,7 @@ timestamp_zone(PG_FUNCTION_ARGS)
 	 * (to handle cases like "America/New_York"), and if that fails, we look
 	 * in the date token table (to handle cases like "EST").
 	 */
-	len = Min(VARSIZE(zone) - VARHDRSZ, TZ_STRLEN_MAX);
-	memcpy(tzname, VARDATA(zone), len);
-	tzname[len] = '\0';
+	text_to_cstring_buffer(zone, tzname, sizeof(tzname));
 	tzp = pg_tzset(tzname);
 	if (tzp)
 	{
@@ -4428,8 +4421,8 @@ timestamp_zone(PG_FUNCTION_ARGS)
 		int			type,
 					val;
 
-		lowzone = downcase_truncate_identifier(VARDATA(zone),
-											   VARSIZE(zone) - VARHDRSZ,
+		lowzone = downcase_truncate_identifier(tzname,
+											   strlen(tzname),
 											   false);
 		type = DecodeSpecial(0, lowzone, &val);
 
@@ -4558,13 +4551,12 @@ timestamptz_timestamp(PG_FUNCTION_ARGS)
 Datum
 timestamptz_zone(PG_FUNCTION_ARGS)
 {
-	text	   *zone = PG_GETARG_TEXT_P(0);
+	text	   *zone = PG_GETARG_TEXT_PP(0);
 	TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(1);
 	Timestamp	result;
 	int			tz;
 	pg_tz	   *tzp;
 	char		tzname[TZ_STRLEN_MAX + 1];
-	int			len;
 
 	if (TIMESTAMP_NOT_FINITE(timestamp))
 		PG_RETURN_TIMESTAMP(timestamp);
@@ -4574,9 +4566,7 @@ timestamptz_zone(PG_FUNCTION_ARGS)
 	 * (to handle cases like "America/New_York"), and if that fails, we look
 	 * in the date token table (to handle cases like "EST").
 	 */
-	len = Min(VARSIZE(zone) - VARHDRSZ, TZ_STRLEN_MAX);
-	memcpy(tzname, VARDATA(zone), len);
-	tzname[len] = '\0';
+	text_to_cstring_buffer(zone, tzname, sizeof(tzname));
 	tzp = pg_tzset(tzname);
 	if (tzp)
 	{
@@ -4600,8 +4590,8 @@ timestamptz_zone(PG_FUNCTION_ARGS)
 		int			type,
 					val;
 
-		lowzone = downcase_truncate_identifier(VARDATA(zone),
-											   VARSIZE(zone) - VARHDRSZ,
+		lowzone = downcase_truncate_identifier(tzname,
+											   strlen(tzname),
 											   false);
 		type = DecodeSpecial(0, lowzone, &val);
 
diff --git a/src/backend/utils/adt/tsginidx.c b/src/backend/utils/adt/tsginidx.c
index 96510021f6de16a05d91f0f69bf35130d9c658f2..add1fc1910c7a7eb926961069834462b514be336 100644
--- a/src/backend/utils/adt/tsginidx.c
+++ b/src/backend/utils/adt/tsginidx.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/tsginidx.c,v 1.9 2008/01/01 19:45:52 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/tsginidx.c,v 1.10 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 #include "access/skey.h"
 #include "tsearch/ts_type.h"
 #include "tsearch/ts_utils.h"
+#include "utils/builtins.h"
 
 
 Datum
@@ -35,11 +36,9 @@ gin_extract_tsvector(PG_FUNCTION_ARGS)
 
 		for (i = 0; i < vector->size; i++)
 		{
-			text	   *txt = (text *) palloc(VARHDRSZ + we->len);
-
-			SET_VARSIZE(txt, VARHDRSZ + we->len);
-			memcpy(VARDATA(txt), STRPTR(vector) + we->pos, we->len);
+			text	   *txt;
 
+			txt = cstring_to_text_with_len(STRPTR(vector) + we->pos, we->len);
 			entries[i] = PointerGetDatum(txt);
 
 			we++;
@@ -87,11 +86,8 @@ gin_extract_tsquery(PG_FUNCTION_ARGS)
 				text	   *txt;
 				QueryOperand *val = &item[i].operand;
 
-				txt = (text *) palloc(VARHDRSZ + val->length);
-
-				SET_VARSIZE(txt, VARHDRSZ + val->length);
-				memcpy(VARDATA(txt), GETOPERAND(query) + val->distance, val->length);
-
+				txt = cstring_to_text_with_len(GETOPERAND(query) + val->distance,
+											   val->length);
 				entries[j++] = PointerGetDatum(txt);
 
 				if (strategy != TSearchWithClassStrategyNumber && val->weight != 0)
diff --git a/src/backend/utils/adt/tsquery.c b/src/backend/utils/adt/tsquery.c
index 41863fb5db54162d9ee213e2c6c47dc8d75aa9db..d84d4ad931ee137ec73b58a08d1f2f8ab5315da3 100644
--- a/src/backend/utils/adt/tsquery.c
+++ b/src/backend/utils/adt/tsquery.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/tsquery.c,v 1.15 2008/01/08 01:04:08 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/tsquery.c,v 1.16 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,7 @@
 #include "tsearch/ts_locale.h"
 #include "tsearch/ts_type.h"
 #include "tsearch/ts_utils.h"
+#include "utils/builtins.h"
 #include "utils/memutils.h"
 #include "utils/pg_crc.h"
 
@@ -954,9 +955,7 @@ tsquerytree(PG_FUNCTION_ARGS)
 
 	if (!q)
 	{
-		res = (text *) palloc(1 + VARHDRSZ);
-		SET_VARSIZE(res, 1 + VARHDRSZ);
-		*((char *) VARDATA(res)) = 'T';
+		res = cstring_to_text("T");
 	}
 	else
 	{
@@ -966,14 +965,11 @@ tsquerytree(PG_FUNCTION_ARGS)
 		*(nrm.cur) = '\0';
 		nrm.op = GETOPERAND(query);
 		infix(&nrm, true);
-
-		res = (text *) palloc(nrm.cur - nrm.buf + VARHDRSZ);
-		SET_VARSIZE(res, nrm.cur - nrm.buf + VARHDRSZ);
-		strncpy(VARDATA(res), nrm.buf, nrm.cur - nrm.buf);
+		res = cstring_to_text_with_len(nrm.buf, nrm.cur - nrm.buf);
 		pfree(q);
 	}
 
 	PG_FREE_IF_COPY(query, 0);
 
-	PG_RETURN_POINTER(res);
+	PG_RETURN_TEXT_P(res);
 }
diff --git a/src/backend/utils/adt/tsquery_rewrite.c b/src/backend/utils/adt/tsquery_rewrite.c
index 89f11731dd4fd9c6cf7fe5605279525b63054554..df917642062b17f05e150373bcf5dcfdf32a1f8e 100644
--- a/src/backend/utils/adt/tsquery_rewrite.c
+++ b/src/backend/utils/adt/tsquery_rewrite.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/tsquery_rewrite.c,v 1.11 2008/01/01 19:45:53 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/tsquery_rewrite.c,v 1.12 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -273,7 +273,7 @@ tsquery_rewrite_query(PG_FUNCTION_ARGS)
 	QTNTernary(tree);
 	QTNSort(tree);
 
-	buf = TextPGetCString(in);
+	buf = text_to_cstring(in);
 
 	SPI_connect();
 
diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c
index eee15a673ddf66f540411c4b660598703053a279..0624c00ea91f9b35f6601809e782238775ea70f9 100644
--- a/src/backend/utils/adt/tsvector_op.c
+++ b/src/backend/utils/adt/tsvector_op.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/tsvector_op.c,v 1.13 2008/03/05 15:50:37 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/tsvector_op.c,v 1.14 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1082,7 +1082,7 @@ ts_process_call(FuncCallContext *funcctx)
 static tsstat *
 ts_stat_sql(text *txt, text *ws)
 {
-	char	   *query = TextPGetCString(txt);
+	char	   *query = text_to_cstring(txt);
 	int			i;
 	tsstat	   *newstat,
 			   *stat;
diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c
index c954e2034ad37320274547d52b77847ffa26a809..49ce0ef4d69c8bb54f01f6db0e116eb0c92f5426 100644
--- a/src/backend/utils/adt/varchar.c
+++ b/src/backend/utils/adt/varchar.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.126 2008/01/01 19:45:53 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.127 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -203,21 +203,16 @@ bpcharin(PG_FUNCTION_ARGS)
 
 /*
  * Convert a CHARACTER value to a C string.
+ *
+ * Uses the text conversion functions, which is only appropriate if BpChar
+ * and text are equivalent types.
  */
 Datum
 bpcharout(PG_FUNCTION_ARGS)
 {
-	BpChar	   *s = PG_GETARG_BPCHAR_PP(0);
-	char	   *result;
-	int			len;
+	Datum		txt = PG_GETARG_DATUM(0);
 
-	/* copy and add null term */
-	len = VARSIZE_ANY_EXHDR(s);
-	result = (char *) palloc(len + 1);
-	memcpy(result, VARDATA_ANY(s), len);
-	result[len] = '\0';
-
-	PG_RETURN_CSTRING(result);
+	PG_RETURN_CSTRING(TextDatumGetCString(txt));
 }
 
 /*
@@ -403,19 +398,17 @@ bpchar_name(PG_FUNCTION_ARGS)
 
 /* name_bpchar()
  * Converts a NameData type to a bpchar type.
+ *
+ * Uses the text conversion functions, which is only appropriate if BpChar
+ * and text are equivalent types.
  */
 Datum
 name_bpchar(PG_FUNCTION_ARGS)
 {
 	Name		s = PG_GETARG_NAME(0);
 	BpChar	   *result;
-	int			len;
-
-	len = strlen(NameStr(*s));
-	result = (BpChar *) palloc(VARHDRSZ + len);
-	memcpy(VARDATA(result), NameStr(*s), len);
-	SET_VARSIZE(result, VARHDRSZ + len);
 
+	result = (BpChar *) cstring_to_text(NameStr(*s));
 	PG_RETURN_BPCHAR_P(result);
 }
 
@@ -454,6 +447,9 @@ bpchartypmodout(PG_FUNCTION_ARGS)
  *
  * If the input string is too long, raise an error, unless the extra
  * characters are spaces, in which case they're truncated.  (per SQL)
+ *
+ * Uses the C string to text conversion function, which is only appropriate
+ * if VarChar and text are equivalent types.
  */
 static VarChar *
 varchar_input(const char *s, size_t len, int32 atttypmod)
@@ -481,10 +477,7 @@ varchar_input(const char *s, size_t len, int32 atttypmod)
 		len = mbmaxlen;
 	}
 
-	result = (VarChar *) palloc(len + VARHDRSZ);
-	SET_VARSIZE(result, len + VARHDRSZ);
-	memcpy(VARDATA(result), s, len);
-
+	result = (VarChar *) cstring_to_text_with_len(s, len);
 	return result;
 }
 
@@ -510,21 +503,16 @@ varcharin(PG_FUNCTION_ARGS)
 
 /*
  * Convert a VARCHAR value to a C string.
+ *
+ * Uses the text to C string conversion function, which is only appropriate
+ * if VarChar and text are equivalent types.
  */
 Datum
 varcharout(PG_FUNCTION_ARGS)
 {
-	VarChar    *s = PG_GETARG_VARCHAR_PP(0);
-	char	   *result;
-	int32		len;
-
-	/* copy and add null term */
-	len = VARSIZE_ANY_EXHDR(s);
-	result = palloc(len + 1);
-	memcpy(result, VARDATA_ANY(s), len);
-	result[len] = '\0';
+	Datum		txt = PG_GETARG_DATUM(0);
 
-	PG_RETURN_CSTRING(result);
+	PG_RETURN_CSTRING(TextDatumGetCString(txt));
 }
 
 /*
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 75832856b6c7e89af7e4295929c9a447648a3e2f..aa56317c7ff5dbaae560abf3877548f7d3fa3a31 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.163 2008/03/13 18:31:56 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.164 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,15 +48,6 @@ typedef struct
 #define PG_GETARG_UNKNOWN_P_COPY(n) DatumGetUnknownPCopy(PG_GETARG_DATUM(n))
 #define PG_RETURN_UNKNOWN_P(x)		PG_RETURN_POINTER(x)
 
-#define PG_TEXTARG_GET_STR(arg_) \
-	DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(arg_)))
-#define PG_TEXT_GET_STR(textp_) \
-	DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp_)))
-#define PG_STR_GET_TEXT(str_) \
-	DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(str_)))
-#define TEXTLEN(textp) \
-	text_length(PointerGetDatum(textp))
-
 static int	text_cmp(text *arg1, text *arg2);
 static int32 text_length(Datum str);
 static int	text_position(text *t1, text *t2);
@@ -67,10 +58,107 @@ static text *text_substring(Datum str,
 			   int32 start,
 			   int32 length,
 			   bool length_not_specified);
-
 static void appendStringInfoText(StringInfo str, const text *t);
 
 
+/*****************************************************************************
+ *	 CONVERSION ROUTINES EXPORTED FOR USE BY C CODE							 *
+ *****************************************************************************/
+
+/*
+ * cstring_to_text
+ *
+ * Create a text value from a null-terminated C string.
+ *
+ * The new text value is freshly palloc'd with a full-size VARHDR.
+ */
+text *
+cstring_to_text(const char *s)
+{
+	return cstring_to_text_with_len(s, strlen(s));
+}
+
+/*
+ * cstring_to_text_with_len
+ *
+ * Same as cstring_to_text except the caller specifies the string length;
+ * the string need not be null_terminated.
+ */
+text *
+cstring_to_text_with_len(const char *s, int len)
+{
+	text	   *result = (text *) palloc(len + VARHDRSZ);
+
+	SET_VARSIZE(result, len + VARHDRSZ);
+	memcpy(VARDATA(result), s, len);
+
+	return result;
+}
+
+/*
+ * text_to_cstring
+ *
+ * Create a palloc'd, null-terminated C string from a text value.
+ *
+ * We support being passed a compressed or toasted text value.
+ * This is a bit bogus since such values shouldn't really be referred to as
+ * "text *", but it seems useful for robustness.  If we didn't handle that
+ * case here, we'd need another routine that did, anyway.
+ */
+char *
+text_to_cstring(const text *t)
+{
+	/* must cast away the const, unfortunately */
+	text	   *tunpacked = pg_detoast_datum_packed((struct varlena *) t);
+	int			len = VARSIZE_ANY_EXHDR(tunpacked);
+	char	   *result;
+
+	result = (char *) palloc(len + 1);
+	memcpy(result, VARDATA_ANY(tunpacked), len);
+	result[len] = '\0';
+
+	if (tunpacked != t)
+		pfree(tunpacked);
+	
+	return result;
+}
+
+/*
+ * text_to_cstring_buffer
+ *
+ * Copy a text value into a caller-supplied buffer of size dst_len.
+ *
+ * The text string is truncated if necessary to fit.  The result is
+ * guaranteed null-terminated (unless dst_len == 0).
+ *
+ * We support being passed a compressed or toasted text value.
+ * This is a bit bogus since such values shouldn't really be referred to as
+ * "text *", but it seems useful for robustness.  If we didn't handle that
+ * case here, we'd need another routine that did, anyway.
+ */
+void
+text_to_cstring_buffer(const text *src, char *dst, size_t dst_len)
+{
+	/* must cast away the const, unfortunately */
+	text	   *srcunpacked = pg_detoast_datum_packed((struct varlena *) src);
+	size_t		src_len = VARSIZE_ANY_EXHDR(srcunpacked);
+
+	if (dst_len > 0)
+	{
+		dst_len--;
+		if (dst_len >= src_len)
+			dst_len = src_len;
+		else					/* ensure truncation is encoding-safe */
+			dst_len = pg_mbcliplen(VARDATA_ANY(srcunpacked), src_len, dst_len);
+		memcpy(dst, VARDATA_ANY(srcunpacked), dst_len);
+		dst[dst_len] = '\0';
+	}
+
+	if (srcunpacked != src)
+		pfree(srcunpacked);
+}
+
+
 /*****************************************************************************
  *	 USER I/O ROUTINES														 *
  *****************************************************************************/
@@ -259,16 +347,8 @@ Datum
 textin(PG_FUNCTION_ARGS)
 {
 	char	   *inputText = PG_GETARG_CSTRING(0);
-	text	   *result;
-	int			len;
-
-	len = strlen(inputText);
-	result = (text *) palloc(len + VARHDRSZ);
-	SET_VARSIZE(result, len + VARHDRSZ);
 
-	memcpy(VARDATA(result), inputText, len);
-
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(inputText));
 }
 
 /*
@@ -277,16 +357,9 @@ textin(PG_FUNCTION_ARGS)
 Datum
 textout(PG_FUNCTION_ARGS)
 {
-	text	   *t = PG_GETARG_TEXT_PP(0);
-	int			len;
-	char	   *result;
+	Datum		txt = PG_GETARG_DATUM(0);
 
-	len = VARSIZE_ANY_EXHDR(t);
-	result = (char *) palloc(len + 1);
-	memcpy(result, VARDATA_ANY(t), len);
-	result[len] = '\0';
-
-	PG_RETURN_CSTRING(result);
+	PG_RETURN_CSTRING(TextDatumGetCString(txt));
 }
 
 /*
@@ -302,9 +375,7 @@ textrecv(PG_FUNCTION_ARGS)
 
 	str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
 
-	result = (text *) palloc(nbytes + VARHDRSZ);
-	SET_VARSIZE(result, nbytes + VARHDRSZ);
-	memcpy(VARDATA(result), str, nbytes);
+	result = cstring_to_text_with_len(str, nbytes);
 	pfree(str);
 	PG_RETURN_TEXT_P(result);
 }
@@ -600,7 +671,7 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
 			 * string.
 			 */
 			if (E < 1)
-				return PG_STR_GET_TEXT("");
+				return cstring_to_text("");
 
 			L1 = E - S1;
 		}
@@ -664,7 +735,7 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
 			 * string.
 			 */
 			if (E < 1)
-				return PG_STR_GET_TEXT("");
+				return cstring_to_text("");
 
 			/*
 			 * if E is past the end of the string, the tuple toaster will
@@ -693,7 +764,7 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
 		{
 			if (slice != (text *) DatumGetPointer(str))
 				pfree(slice);
-			return PG_STR_GET_TEXT("");
+			return cstring_to_text("");
 		}
 
 		/* Now we can get the actual length of the slice in MB characters */
@@ -708,7 +779,7 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
 		{
 			if (slice != (text *) DatumGetPointer(str))
 				pfree(slice);
-			return PG_STR_GET_TEXT("");
+			return cstring_to_text("");
 		}
 
 		/*
@@ -1759,16 +1830,8 @@ Datum
 name_text(PG_FUNCTION_ARGS)
 {
 	Name		s = PG_GETARG_NAME(0);
-	text	   *result;
-	int			len;
-
-	len = strlen(NameStr(*s));
-
-	result = palloc(VARHDRSZ + len);
-	SET_VARSIZE(result, VARHDRSZ + len);
-	memcpy(VARDATA(result), NameStr(*s), len);
 
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TEXT_P(cstring_to_text(NameStr(*s)));
 }
 
 
@@ -1790,8 +1853,7 @@ textToQualifiedNameList(text *textval)
 
 	/* Convert to C string (handles possible detoasting). */
 	/* Note we rely on being able to modify rawname below. */
-	rawname = DatumGetCString(DirectFunctionCall1(textout,
-												  PointerGetDatum(textval)));
+	rawname = text_to_cstring(textval);
 
 	if (!SplitIdentifierString(rawname, '.', &namelist))
 		ereport(ERROR,
@@ -2103,7 +2165,7 @@ byteacmp(PG_FUNCTION_ARGS)
  * appendStringInfoText
  *
  * Append a text to str.
- * Like appendStringInfoString(str, PG_TEXT_GET_STR(s)) but faster.
+ * Like appendStringInfoString(str, text_to_cstring(t)) but faster.
  */
 static void
 appendStringInfoText(StringInfo str, const text *t)
@@ -2191,7 +2253,7 @@ replace_text(PG_FUNCTION_ARGS)
 
 	text_position_cleanup(&state);
 
-	ret_text = PG_STR_GET_TEXT(str.data);
+	ret_text = cstring_to_text_with_len(str.data, str.len);
 	pfree(str.data);
 
 	PG_RETURN_TEXT_P(ret_text);
@@ -2458,7 +2520,7 @@ replace_text_regexp(text *src_text, void *regexp,
 		appendBinaryStringInfo(&buf, start_ptr, chunk_len);
 	}
 
-	ret_text = PG_STR_GET_TEXT(buf.data);
+	ret_text = cstring_to_text_with_len(buf.data, buf.len);
 	pfree(buf.data);
 	pfree(data);
 
@@ -2503,7 +2565,7 @@ split_text(PG_FUNCTION_ARGS)
 	if (inputstring_len < 1)
 	{
 		text_position_cleanup(&state);
-		PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
+		PG_RETURN_TEXT_P(cstring_to_text(""));
 	}
 
 	/* empty field separator */
@@ -2514,7 +2576,7 @@ split_text(PG_FUNCTION_ARGS)
 		if (fldnum == 1)
 			PG_RETURN_TEXT_P(inputstring);
 		else
-			PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
+			PG_RETURN_TEXT_P(cstring_to_text(""));
 	}
 
 	/* identify bounds of first field */
@@ -2529,7 +2591,7 @@ split_text(PG_FUNCTION_ARGS)
 		if (fldnum == 1)
 			PG_RETURN_TEXT_P(inputstring);
 		else
-			PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
+			PG_RETURN_TEXT_P(cstring_to_text(""));
 	}
 
 	while (end_posn > 0 && --fldnum > 0)
@@ -2551,7 +2613,7 @@ split_text(PG_FUNCTION_ARGS)
 										 -1,
 										 true);
 		else
-			result_text = PG_STR_GET_TEXT("");
+			result_text = cstring_to_text("");
 	}
 	else
 	{
@@ -2636,9 +2698,7 @@ text_to_array(PG_FUNCTION_ARGS)
 		}
 
 		/* must build a temp text datum to pass to accumArrayResult */
-		result_text = (text *) palloc(VARHDRSZ + chunk_len);
-		SET_VARSIZE(result_text, VARHDRSZ + chunk_len);
-		memcpy(VARDATA(result_text), start_ptr, chunk_len);
+		result_text = cstring_to_text_with_len(start_ptr, chunk_len);
 
 		/* stash away this field */
 		astate = accumArrayResult(astate,
@@ -2673,7 +2733,7 @@ Datum
 array_to_text(PG_FUNCTION_ARGS)
 {
 	ArrayType  *v = PG_GETARG_ARRAYTYPE_P(0);
-	char	   *fldsep = PG_TEXTARG_GET_STR(1);
+	char	   *fldsep = text_to_cstring(PG_GETARG_TEXT_PP(1));
 	int			nitems,
 			   *dims,
 				ndims;
@@ -2695,7 +2755,7 @@ array_to_text(PG_FUNCTION_ARGS)
 
 	/* if there are no elements, return an empty string */
 	if (nitems == 0)
-		PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
+		PG_RETURN_TEXT_P(cstring_to_text(""));
 
 	element_type = ARR_ELEMTYPE(v);
 	initStringInfo(&buf);
@@ -2773,7 +2833,7 @@ array_to_text(PG_FUNCTION_ARGS)
 		}
 	}
 
-	PG_RETURN_TEXT_P(PG_STR_GET_TEXT(buf.data));
+	PG_RETURN_TEXT_P(cstring_to_text_with_len(buf.data, buf.len));
 }
 
 #define HEXBASE 16
@@ -2785,7 +2845,6 @@ Datum
 to_hex32(PG_FUNCTION_ARGS)
 {
 	uint32		value = (uint32) PG_GETARG_INT32(0);
-	text	   *result_text;
 	char	   *ptr;
 	const char *digits = "0123456789abcdef";
 	char		buf[32];		/* bigger than needed, but reasonable */
@@ -2799,8 +2858,7 @@ to_hex32(PG_FUNCTION_ARGS)
 		value /= HEXBASE;
 	} while (ptr > buf && value);
 
-	result_text = PG_STR_GET_TEXT(ptr);
-	PG_RETURN_TEXT_P(result_text);
+	PG_RETURN_TEXT_P(cstring_to_text(ptr));
 }
 
 /*
@@ -2811,7 +2869,6 @@ Datum
 to_hex64(PG_FUNCTION_ARGS)
 {
 	uint64		value = (uint64) PG_GETARG_INT64(0);
-	text	   *result_text;
 	char	   *ptr;
 	const char *digits = "0123456789abcdef";
 	char		buf[32];		/* bigger than needed, but reasonable */
@@ -2825,8 +2882,7 @@ to_hex64(PG_FUNCTION_ARGS)
 		value /= HEXBASE;
 	} while (ptr > buf && value);
 
-	result_text = PG_STR_GET_TEXT(ptr);
-	PG_RETURN_TEXT_P(result_text);
+	PG_RETURN_TEXT_P(cstring_to_text(ptr));
 }
 
 /*
@@ -2842,7 +2898,6 @@ md5_text(PG_FUNCTION_ARGS)
 	text	   *in_text = PG_GETARG_TEXT_PP(0);
 	size_t		len;
 	char		hexsum[MD5_HASH_LEN + 1];
-	text	   *result_text;
 
 	/* Calculate the length of the buffer using varlena metadata */
 	len = VARSIZE_ANY_EXHDR(in_text);
@@ -2854,8 +2909,7 @@ md5_text(PG_FUNCTION_ARGS)
 				 errmsg("out of memory")));
 
 	/* convert to text and return it */
-	result_text = PG_STR_GET_TEXT(hexsum);
-	PG_RETURN_TEXT_P(result_text);
+	PG_RETURN_TEXT_P(cstring_to_text(hexsum));
 }
 
 /*
@@ -2868,7 +2922,6 @@ md5_bytea(PG_FUNCTION_ARGS)
 	bytea	   *in = PG_GETARG_BYTEA_PP(0);
 	size_t		len;
 	char		hexsum[MD5_HASH_LEN + 1];
-	text	   *result_text;
 
 	len = VARSIZE_ANY_EXHDR(in);
 	if (pg_md5_hash(VARDATA_ANY(in), len, hexsum) == false)
@@ -2876,8 +2929,7 @@ md5_bytea(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_OUT_OF_MEMORY),
 				 errmsg("out of memory")));
 
-	result_text = PG_STR_GET_TEXT(hexsum);
-	PG_RETURN_TEXT_P(result_text);
+	PG_RETURN_TEXT_P(cstring_to_text(hexsum));
 }
 
 /*
diff --git a/src/backend/utils/adt/version.c b/src/backend/utils/adt/version.c
index 0ffe0da042990d796e053eec59ec31acdb86cfc7..1a2619c4c6e16604bc0a1b243bd17ffee5ab17d3 100644
--- a/src/backend/utils/adt/version.c
+++ b/src/backend/utils/adt/version.c
@@ -7,7 +7,7 @@
  *
  * IDENTIFICATION
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/version.c,v 1.16 2008/01/01 19:45:53 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/version.c,v 1.17 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,11 +20,5 @@
 Datum
 pgsql_version(PG_FUNCTION_ARGS)
 {
-	int			n = strlen(PG_VERSION_STR);
-	text	   *ret = (text *) palloc(n + VARHDRSZ);
-
-	SET_VARSIZE(ret, n + VARHDRSZ);
-	memcpy(VARDATA(ret), PG_VERSION_STR, n);
-
-	PG_RETURN_TEXT_P(ret);
+	PG_RETURN_TEXT_P(cstring_to_text(PG_VERSION_STR));
 }
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index f0a668b292786c27c528ed0884130b6eeec2c18e..c4960bcecfbf3659feff0622cbd0c81b243776c2 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.70 2008/03/24 19:12:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.71 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -141,10 +141,6 @@ static void SPI_sql_row_to_xmlelement(int rownum, StringInfo result,
 			 errhint("You need to rebuild PostgreSQL using --with-libxml.")))
 
 
-#define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str))
-#define _textout(x) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(x)))
-
-
 /* from SQL/XML:2003 section 4.7 */
 #define NAMESPACE_XSD "http://www.w3.org/2001/XMLSchema"
 #define NAMESPACE_XSI "http://www.w3.org/2001/XMLSchema-instance"
@@ -168,19 +164,22 @@ xmlChar_to_encoding(xmlChar * encoding_name)
 #endif
 
 
+/*
+ * xml_in uses a plain C string to VARDATA conversion, so for the time being
+ * we use the conversion function for the text datatype.
+ *
+ * This is only acceptable so long as xmltype and text use the same
+ * representation.
+ */
 Datum
 xml_in(PG_FUNCTION_ARGS)
 {
 #ifdef USE_LIBXML
 	char	   *s = PG_GETARG_CSTRING(0);
-	size_t		len;
 	xmltype    *vardata;
 	xmlDocPtr	doc;
 
-	len = strlen(s);
-	vardata = palloc(len + VARHDRSZ);
-	SET_VARSIZE(vardata, len + VARHDRSZ);
-	memcpy(VARDATA(vardata), s, len);
+	vardata = (xmltype *) cstring_to_text(s);
 
 	/*
 	 * Parse the data to check if it is well-formed XML data.  Assume that
@@ -200,6 +199,13 @@ xml_in(PG_FUNCTION_ARGS)
 #define PG_XML_DEFAULT_VERSION "1.0"
 
 
+/*
+ * xml_out_internal uses a plain VARDATA to C string conversion, so for the
+ * time being we use the conversion function for the text datatype.
+ *
+ * This is only acceptable so long as xmltype and text use the same
+ * representation.
+ */
 static char *
 xml_out_internal(xmltype *x, pg_enc target_encoding)
 {
@@ -213,10 +219,8 @@ xml_out_internal(xmltype *x, pg_enc target_encoding)
 	int			res_code;
 #endif
 
-	len = VARSIZE(x) - VARHDRSZ;
-	str = palloc(len + 1);
-	memcpy(str, VARDATA(x), len);
-	str[len] = '\0';
+	str = text_to_cstring((text *) x);
+	len = strlen(str);
 
 #ifdef USE_LIBXML
 	if ((res_code = parse_xml_decl((xmlChar *) str,
@@ -713,7 +717,7 @@ xmlpi(char *target, text *arg, bool arg_is_null, bool *result_is_null)
 	{
 		char	   *string;
 
-		string = _textout(arg);
+		string = text_to_cstring(arg);
 		if (strstr(string, "?>") != NULL)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
@@ -1930,7 +1934,7 @@ table_to_xml(PG_FUNCTION_ARGS)
 	Oid			relid = PG_GETARG_OID(0);
 	bool		nulls = PG_GETARG_BOOL(1);
 	bool		tableforest = PG_GETARG_BOOL(2);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(3));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
 
 	PG_RETURN_XML_P(stringinfo_to_xmltype(table_to_xml_internal(relid, NULL,
 														  nulls, tableforest,
@@ -1941,10 +1945,10 @@ table_to_xml(PG_FUNCTION_ARGS)
 Datum
 query_to_xml(PG_FUNCTION_ARGS)
 {
-	char	   *query = _textout(PG_GETARG_TEXT_P(0));
+	char	   *query = text_to_cstring(PG_GETARG_TEXT_PP(0));
 	bool		nulls = PG_GETARG_BOOL(1);
 	bool		tableforest = PG_GETARG_BOOL(2);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(3));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
 
 	PG_RETURN_XML_P(stringinfo_to_xmltype(query_to_xml_internal(query, NULL,
 													NULL, nulls, tableforest,
@@ -1955,11 +1959,11 @@ query_to_xml(PG_FUNCTION_ARGS)
 Datum
 cursor_to_xml(PG_FUNCTION_ARGS)
 {
-	char	   *name = _textout(PG_GETARG_TEXT_P(0));
+	char	   *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
 	int32		count = PG_GETARG_INT32(1);
 	bool		nulls = PG_GETARG_BOOL(2);
 	bool		tableforest = PG_GETARG_BOOL(3);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(4));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(4));
 
 	StringInfoData result;
 	Portal		portal;
@@ -2079,7 +2083,7 @@ table_to_xmlschema(PG_FUNCTION_ARGS)
 	Oid			relid = PG_GETARG_OID(0);
 	bool		nulls = PG_GETARG_BOOL(1);
 	bool		tableforest = PG_GETARG_BOOL(2);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(3));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
 	const char *result;
 	Relation	rel;
 
@@ -2095,10 +2099,10 @@ table_to_xmlschema(PG_FUNCTION_ARGS)
 Datum
 query_to_xmlschema(PG_FUNCTION_ARGS)
 {
-	char	   *query = _textout(PG_GETARG_TEXT_P(0));
+	char	   *query = text_to_cstring(PG_GETARG_TEXT_PP(0));
 	bool		nulls = PG_GETARG_BOOL(1);
 	bool		tableforest = PG_GETARG_BOOL(2);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(3));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
 	const char *result;
 	SPIPlanPtr	plan;
 	Portal		portal;
@@ -2124,10 +2128,10 @@ query_to_xmlschema(PG_FUNCTION_ARGS)
 Datum
 cursor_to_xmlschema(PG_FUNCTION_ARGS)
 {
-	char	   *name = _textout(PG_GETARG_TEXT_P(0));
+	char	   *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
 	bool		nulls = PG_GETARG_BOOL(1);
 	bool		tableforest = PG_GETARG_BOOL(2);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(3));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
 	const char *xmlschema;
 	Portal		portal;
 
@@ -2153,7 +2157,7 @@ table_to_xml_and_xmlschema(PG_FUNCTION_ARGS)
 	Oid			relid = PG_GETARG_OID(0);
 	bool		nulls = PG_GETARG_BOOL(1);
 	bool		tableforest = PG_GETARG_BOOL(2);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(3));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
 	Relation	rel;
 	const char *xmlschema;
 
@@ -2171,10 +2175,10 @@ table_to_xml_and_xmlschema(PG_FUNCTION_ARGS)
 Datum
 query_to_xml_and_xmlschema(PG_FUNCTION_ARGS)
 {
-	char	   *query = _textout(PG_GETARG_TEXT_P(0));
+	char	   *query = text_to_cstring(PG_GETARG_TEXT_PP(0));
 	bool		nulls = PG_GETARG_BOOL(1);
 	bool		tableforest = PG_GETARG_BOOL(2);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(3));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
 
 	const char *xmlschema;
 	SPIPlanPtr	plan;
@@ -2255,7 +2259,7 @@ schema_to_xml(PG_FUNCTION_ARGS)
 	Name		name = PG_GETARG_NAME(0);
 	bool		nulls = PG_GETARG_BOOL(1);
 	bool		tableforest = PG_GETARG_BOOL(2);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(3));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
 
 	char	   *schemaname;
 	Oid			nspid;
@@ -2346,7 +2350,7 @@ schema_to_xmlschema(PG_FUNCTION_ARGS)
 	Name		name = PG_GETARG_NAME(0);
 	bool		nulls = PG_GETARG_BOOL(1);
 	bool		tableforest = PG_GETARG_BOOL(2);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(3));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
 
 	PG_RETURN_XML_P(stringinfo_to_xmltype(schema_to_xmlschema_internal(NameStr(*name),
 											 nulls, tableforest, targetns)));
@@ -2359,7 +2363,7 @@ schema_to_xml_and_xmlschema(PG_FUNCTION_ARGS)
 	Name		name = PG_GETARG_NAME(0);
 	bool		nulls = PG_GETARG_BOOL(1);
 	bool		tableforest = PG_GETARG_BOOL(2);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(3));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
 	char	   *schemaname;
 	Oid			nspid;
 	StringInfo	xmlschema;
@@ -2431,7 +2435,7 @@ database_to_xml(PG_FUNCTION_ARGS)
 {
 	bool		nulls = PG_GETARG_BOOL(0);
 	bool		tableforest = PG_GETARG_BOOL(1);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(2));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(2));
 
 	PG_RETURN_XML_P(stringinfo_to_xmltype(database_to_xml_internal(NULL, nulls,
 													tableforest, targetns)));
@@ -2486,7 +2490,7 @@ database_to_xmlschema(PG_FUNCTION_ARGS)
 {
 	bool		nulls = PG_GETARG_BOOL(0);
 	bool		tableforest = PG_GETARG_BOOL(1);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(2));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(2));
 
 	PG_RETURN_XML_P(stringinfo_to_xmltype(database_to_xmlschema_internal(nulls,
 													tableforest, targetns)));
@@ -2498,7 +2502,7 @@ database_to_xml_and_xmlschema(PG_FUNCTION_ARGS)
 {
 	bool		nulls = PG_GETARG_BOOL(0);
 	bool		tableforest = PG_GETARG_BOOL(1);
-	const char *targetns = _textout(PG_GETARG_TEXT_P(2));
+	const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(2));
 	StringInfo	xmlschema;
 
 	xmlschema = database_to_xmlschema_internal(nulls, tableforest, targetns);
@@ -3198,7 +3202,7 @@ xml_xmlnodetoxmltype(xmlNodePtr cur)
 	{
 		str = xmlXPathCastNodeToString(cur);
 		len = strlen((char *) str);
-		result = (text *) palloc(len + VARHDRSZ);
+		result = (xmltype *) palloc(len + VARHDRSZ);
 		SET_VARSIZE(result, len + VARHDRSZ);
 		memcpy(VARDATA(result), str, len);
 	}
@@ -3363,8 +3367,8 @@ xpath(PG_FUNCTION_ARGS)
 				ereport(ERROR,
 						(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 						 errmsg("neither namespace name nor URI may be null")));
-			ns_name = _textout(ns_names_uris[i * 2]);
-			ns_uri = _textout(ns_names_uris[i * 2 + 1]);
+			ns_name = TextDatumGetCString(ns_names_uris[i * 2]);
+			ns_uri = TextDatumGetCString(ns_names_uris[i * 2 + 1]);
 			if (xmlXPathRegisterNs(xpathctx,
 								   (xmlChar *) ns_name,
 								   (xmlChar *) ns_uri) != 0)
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 70872f56c7bcbcc5a2c2bc4beb8e1dc7ddbcfec3..76e39ca8af7fca28a858a8a4f29e17fda09624ce 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.155 2008/01/01 19:45:53 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.156 2008/03/25 22:42:44 tgl Exp $
  *
  * NOTES
  *	  Eventually, the index information should go through here, too.
@@ -1971,8 +1971,7 @@ get_typdefault(Oid typid)
 	if (!isNull)
 	{
 		/* We have an expression default */
-		expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
-																datum)));
+		expr = stringToNode(TextDatumGetCString(datum));
 	}
 	else
 	{
@@ -1987,8 +1986,7 @@ get_typdefault(Oid typid)
 			char	   *strDefaultVal;
 
 			/* Convert text datum to C string */
-			strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
-																datum));
+			strDefaultVal = TextDatumGetCString(datum);
 			/* Convert C string to a value of the given type */
 			datum = OidInputFunctionCall(type->typinput, strDefaultVal,
 										 getTypeIOParam(typeTuple), -1);
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index ca4305c60ba8dd27100e8674b37e2592b47a4636..e6f7eef80051463349d5a765d365fbb03f576a75 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.267 2008/02/27 17:44:19 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.268 2008/03/25 22:42:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -642,7 +642,6 @@ RelationBuildRuleLock(Relation relation)
 		Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(rewrite_tuple);
 		bool		isnull;
 		Datum		rule_datum;
-		text	   *rule_text;
 		char	   *rule_str;
 		RewriteRule *rule;
 
@@ -667,30 +666,22 @@ RelationBuildRuleLock(Relation relation)
 								  rewrite_tupdesc,
 								  &isnull);
 		Assert(!isnull);
-		rule_text = DatumGetTextP(rule_datum);
-		rule_str = DatumGetCString(DirectFunctionCall1(textout,
-												PointerGetDatum(rule_text)));
+		rule_str = TextDatumGetCString(rule_datum);
 		oldcxt = MemoryContextSwitchTo(rulescxt);
 		rule->actions = (List *) stringToNode(rule_str);
 		MemoryContextSwitchTo(oldcxt);
 		pfree(rule_str);
-		if ((Pointer) rule_text != DatumGetPointer(rule_datum))
-			pfree(rule_text);
 
 		rule_datum = heap_getattr(rewrite_tuple,
 								  Anum_pg_rewrite_ev_qual,
 								  rewrite_tupdesc,
 								  &isnull);
 		Assert(!isnull);
-		rule_text = DatumGetTextP(rule_datum);
-		rule_str = DatumGetCString(DirectFunctionCall1(textout,
-												PointerGetDatum(rule_text)));
+		rule_str = TextDatumGetCString(rule_datum);
 		oldcxt = MemoryContextSwitchTo(rulescxt);
 		rule->qual = (Node *) stringToNode(rule_str);
 		MemoryContextSwitchTo(oldcxt);
 		pfree(rule_str);
-		if ((Pointer) rule_text != DatumGetPointer(rule_datum))
-			pfree(rule_text);
 
 		/*
 		 * We want the rule's table references to be checked as though by the
@@ -2770,8 +2761,7 @@ AttrDefaultFetch(Relation relation)
 					 RelationGetRelationName(relation));
 			else
 				attrdef[i].adbin = MemoryContextStrdup(CacheMemoryContext,
-								 DatumGetCString(DirectFunctionCall1(textout,
-																	 val)));
+													TextDatumGetCString(val));
 			break;
 		}
 
@@ -2834,8 +2824,7 @@ CheckConstraintFetch(Relation relation)
 				 RelationGetRelationName(relation));
 
 		check[found].ccbin = MemoryContextStrdup(CacheMemoryContext,
-								 DatumGetCString(DirectFunctionCall1(textout,
-																	 val)));
+												 TextDatumGetCString(val));
 		found++;
 	}
 
@@ -3068,7 +3057,7 @@ RelationGetIndexExpressions(Relation relation)
 							  GetPgIndexDescriptor(),
 							  &isnull);
 	Assert(!isnull);
-	exprsString = DatumGetCString(DirectFunctionCall1(textout, exprsDatum));
+	exprsString = TextDatumGetCString(exprsDatum);
 	result = (List *) stringToNode(exprsString);
 	pfree(exprsString);
 
@@ -3135,7 +3124,7 @@ RelationGetIndexPredicate(Relation relation)
 							 GetPgIndexDescriptor(),
 							 &isnull);
 	Assert(!isnull);
-	predString = DatumGetCString(DirectFunctionCall1(textout, predDatum));
+	predString = TextDatumGetCString(predDatum);
 	result = (List *) stringToNode(predString);
 	pfree(predString);
 
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 19216b4381cf86fd91c1f1e2eea36cd360db842c..e06da243ab0763b8302e5a1873b767efdff80a1c 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.113 2008/01/03 21:23:15 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.114 2008/03/25 22:42:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -246,8 +246,7 @@ fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
 										  Anum_pg_proc_prosrc, &isnull);
 			if (isnull)
 				elog(ERROR, "null prosrc");
-			prosrc = DatumGetCString(DirectFunctionCall1(textout,
-														 prosrcdatum));
+			prosrc = TextDatumGetCString(prosrcdatum);
 			fbp = fmgr_lookupByName(prosrc);
 			if (fbp == NULL)
 				ereport(ERROR,
@@ -315,15 +314,13 @@ fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
 									 Anum_pg_proc_prosrc, &isnull);
 		if (isnull)
 			elog(ERROR, "null prosrc for function %u", functionId);
-		prosrcstring = DatumGetCString(DirectFunctionCall1(textout,
-														   prosrcattr));
+		prosrcstring = TextDatumGetCString(prosrcattr);
 
 		probinattr = SysCacheGetAttr(PROCOID, procedureTuple,
 									 Anum_pg_proc_probin, &isnull);
 		if (isnull)
 			elog(ERROR, "null probin for function %u", functionId);
-		probinstring = DatumGetCString(DirectFunctionCall1(textout,
-														   probinattr));
+		probinstring = TextDatumGetCString(probinattr);
 
 		/* Look up the function itself */
 		user_fn = load_external_function(probinstring, prosrcstring, true,
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index 4bb230a3f364892af44fb4056190a48edcc30caf..42586f13aa16cafccb6bd74f94a4f69616f1f41f 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -7,7 +7,7 @@
  * Copyright (c) 2002-2008, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.38 2008/02/29 02:49:39 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.39 2008/03/25 22:42:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -741,8 +741,7 @@ get_func_arg_info(HeapTuple procTup,
 			elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
 		*p_argnames = (char **) palloc(sizeof(char *) * numargs);
 		for (i = 0; i < numargs; i++)
-			(*p_argnames)[i] = DatumGetCString(DirectFunctionCall1(textout,
-																   elems[i]));
+			(*p_argnames)[i] = TextDatumGetCString(elems[i]);
 	}
 
 	/* Get argument modes, if available */
@@ -855,8 +854,7 @@ get_func_result_name(Oid functionId)
 				result = NULL;
 				break;
 			}
-			result = DatumGetCString(DirectFunctionCall1(textout,
-														 argnames[i]));
+			result = TextDatumGetCString(argnames[i]);
 			if (result == NULL || result[0] == '\0')
 			{
 				/* Parameter is not named, so forget it */
@@ -1002,7 +1000,7 @@ build_function_result_tupdesc_d(Datum proallargtypes,
 			   argmodes[i] == PROARGMODE_INOUT);
 		outargtypes[numoutargs] = argtypes[i];
 		if (argnames)
-			pname = DatumGetCString(DirectFunctionCall1(textout, argnames[i]));
+			pname = TextDatumGetCString(argnames[i]);
 		else
 			pname = NULL;
 		if (pname == NULL || pname[0] == '\0')
diff --git a/src/backend/utils/init/flatfiles.c b/src/backend/utils/init/flatfiles.c
index aa155a07bb3c52efeca5c1580a8e9cc1b95ef921..cffbc51bbdc9dbd7a31cee5fc5b5f459d5ba83a7 100644
--- a/src/backend/utils/init/flatfiles.c
+++ b/src/backend/utils/init/flatfiles.c
@@ -23,7 +23,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.30 2008/01/01 19:45:53 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.31 2008/03/25 22:42:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -461,13 +461,14 @@ write_auth_file(Relation rel_authid, Relation rel_authmem)
 			 * it is, ignore it, since we can't handle that in startup mode.
 			 *
 			 * It is entirely likely that it's 1-byte format not 4-byte, and
-			 * theoretically possible that it's compressed inline, but textout
-			 * should be able to handle those cases even in startup mode.
+			 * theoretically possible that it's compressed inline, but
+			 * text_to_cstring should be able to handle those cases even in
+			 * startup mode.
 			 */
 			if (VARATT_IS_EXTERNAL(DatumGetPointer(datum)))
 				auth_info[curr_role].rolpassword = pstrdup("");
 			else
-				auth_info[curr_role].rolpassword = DatumGetCString(DirectFunctionCall1(textout, datum));
+				auth_info[curr_role].rolpassword = TextDatumGetCString(datum);
 
 			/* assume passwd has attlen -1 */
 			off = att_addlength_pointer(off, -1, tp + off);
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 6839a165dd6a53e93d522b8b61757dc831babd84..938b3acd8375050ee2230d90e66de89dab201ed5 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.439 2008/03/17 17:45:09 mha Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.440 2008/03/25 22:42:45 tgl Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -5364,7 +5364,6 @@ set_config_by_name(PG_FUNCTION_ARGS)
 	char	   *value;
 	char	   *new_value;
 	bool		is_local;
-	text	   *result_text;
 
 	if (PG_ARGISNULL(0))
 		ereport(ERROR,
@@ -5372,13 +5371,13 @@ set_config_by_name(PG_FUNCTION_ARGS)
 				 errmsg("SET requires parameter name")));
 
 	/* Get the GUC variable name */
-	name = DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(0)));
+	name = TextDatumGetCString(PG_GETARG_DATUM(0));
 
 	/* Get the desired value or set to NULL for a reset request */
 	if (PG_ARGISNULL(1))
 		value = NULL;
 	else
-		value = DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(1)));
+		value = TextDatumGetCString(PG_GETARG_DATUM(1));
 
 	/*
 	 * Get the desired state of is_local. Default to false if provided value
@@ -5401,10 +5400,7 @@ set_config_by_name(PG_FUNCTION_ARGS)
 	new_value = GetConfigOptionByName(name, NULL);
 
 	/* Convert return string to text */
-	result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(new_value)));
-
-	/* return it */
-	PG_RETURN_TEXT_P(result_text);
+	PG_RETURN_TEXT_P(cstring_to_text(new_value));
 }
 
 
@@ -5992,19 +5988,15 @@ show_config_by_name(PG_FUNCTION_ARGS)
 {
 	char	   *varname;
 	char	   *varval;
-	text	   *result_text;
 
 	/* Get the GUC variable name */
-	varname = DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(0)));
+	varname = TextDatumGetCString(PG_GETARG_DATUM(0));
 
 	/* Get the value */
 	varval = GetConfigOptionByName(varname, NULL);
 
 	/* Convert to text */
-	result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(varval)));
-
-	/* return it */
-	PG_RETURN_TEXT_P(result_text);
+	PG_RETURN_TEXT_P(cstring_to_text(varval));
 }
 
 /*
@@ -6609,7 +6601,7 @@ ProcessGUCArray(ArrayType *array,
 		if (isnull)
 			continue;
 
-		s = DatumGetCString(DirectFunctionCall1(textout, d));
+		s = TextDatumGetCString(d);
 
 		ParseLongOption(s, &name, &value);
 		if (!value)
@@ -6657,7 +6649,7 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
 
 	newval = palloc(strlen(name) + 1 + strlen(value) + 1);
 	sprintf(newval, "%s=%s", name, value);
-	datum = DirectFunctionCall1(textin, CStringGetDatum(newval));
+	datum = CStringGetTextDatum(newval);
 
 	if (array)
 	{
@@ -6684,7 +6676,7 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
 						  &isnull);
 			if (isnull)
 				continue;
-			current = DatumGetCString(DirectFunctionCall1(textout, d));
+			current = TextDatumGetCString(d);
 			if (strncmp(current, newval, strlen(name) + 1) == 0)
 			{
 				index = i;
@@ -6754,7 +6746,7 @@ GUCArrayDelete(ArrayType *array, const char *name)
 					  &isnull);
 		if (isnull)
 			continue;
-		val = DatumGetCString(DirectFunctionCall1(textout, d));
+		val = TextDatumGetCString(d);
 
 		/* ignore entry if it's what we want to delete */
 		if (strncmp(val, name, strlen(name)) == 0
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index 63bf48124a81f7265436fffe0c38d714490d4ed9..4940f7721f68447b203fedbc62350708b3d1b794 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.107 2008/03/25 19:26:53 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.108 2008/03/25 22:42:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -923,12 +923,11 @@ pg_cursor(PG_FUNCTION_ARGS)
 
 		MemSet(nulls, 0, sizeof(nulls));
 
-		values[0] = DirectFunctionCall1(textin, CStringGetDatum(portal->name));
+		values[0] = CStringGetTextDatum(portal->name);
 		if (!portal->sourceText)
 			nulls[1] = true;
 		else
-			values[1] = DirectFunctionCall1(textin,
-										CStringGetDatum(portal->sourceText));
+			values[1] = CStringGetTextDatum(portal->sourceText);
 		values[2] = BoolGetDatum(portal->cursorOptions & CURSOR_OPT_HOLD);
 		values[3] = BoolGetDatum(portal->cursorOptions & CURSOR_OPT_BINARY);
 		values[4] = BoolGetDatum(portal->cursorOptions & CURSOR_OPT_SCROLL);
diff --git a/src/include/tsearch/ts_utils.h b/src/include/tsearch/ts_utils.h
index 7ce5b0cc3cb65a3b67191ad72fab2c4874baccb8..bf0e33e58c06c7999b48dcfd2232bc1ff527f3f0 100644
--- a/src/include/tsearch/ts_utils.h
+++ b/src/include/tsearch/ts_utils.h
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1998-2008, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/tsearch/ts_utils.h,v 1.12 2008/01/01 19:45:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/tsearch/ts_utils.h,v 1.13 2008/03/25 22:42:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -106,12 +106,6 @@ extern text *generateHeadline(HeadlineParsedText *prs);
 extern bool TS_execute(QueryItem *curitem, void *checkval, bool calcnot,
 		   bool (*chkcond) (void *checkval, QueryOperand *val));
 
-/*
- * Useful conversion macros
- */
-#define TextPGetCString(t) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(t)))
-#define CStringGetTextP(c) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(c)))
-
 /*
  * to_ts* - text transformation to tsvector, tsquery
  */
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 5dbc00fce5345cf74d58e311a4f4a2bb6e911d7a..f719b492c145636026fb4220be35fd478a4d526d 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.309 2008/03/23 00:24:20 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.310 2008/03/25 22:42:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -617,6 +617,14 @@ extern Datum varchartypmodout(PG_FUNCTION_ARGS);
 extern Datum varchar(PG_FUNCTION_ARGS);
 
 /* varlena.c */
+extern text *cstring_to_text(const char *s);
+extern text *cstring_to_text_with_len(const char *s, int len);
+extern char *text_to_cstring(const text *t);
+extern void text_to_cstring_buffer(const text *src, char *dst, size_t dst_len);
+
+#define CStringGetTextDatum(s) PointerGetDatum(cstring_to_text(s))
+#define TextDatumGetCString(d) text_to_cstring((text *) DatumGetPointer(d))
+
 extern Datum textin(PG_FUNCTION_ARGS);
 extern Datum textout(PG_FUNCTION_ARGS);
 extern Datum textrecv(PG_FUNCTION_ARGS);
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 3ce8f60c2625bb03c62e4edee11ec4fc6eec633a..9922a4a0edbcf78643868291d1a21073ebac61bd 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -1,7 +1,7 @@
 /**********************************************************************
  * plperl.c - perl as a procedural language for PostgreSQL
  *
- *	  $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.137 2008/03/25 19:26:53 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.138 2008/03/25 22:42:45 tgl Exp $
  *
  **********************************************************************/
 
@@ -542,7 +542,7 @@ plperl_safe_init(void)
 			desc.arg_is_rowtype[0] = false;
 			fmgr_info(F_TEXTOUT, &(desc.arg_out_func[0]));
 
-			fcinfo.arg[0] = DirectFunctionCall1(textin, CStringGetDatum("a"));
+			fcinfo.arg[0] = CStringGetTextDatum("a");
 			fcinfo.argnull[0] = false;
 			
 			/* and make the call */
@@ -1668,8 +1668,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
 									  Anum_pg_proc_prosrc, &isnull);
 		if (isnull)
 			elog(ERROR, "null prosrc");
-		proc_source = DatumGetCString(DirectFunctionCall1(textout,
-														  prosrcdatum));
+		proc_source = TextDatumGetCString(prosrcdatum);
 
 		/************************************************************
 		 * Create the procedure in the interpreter
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index d771b92660a4c1d6e2bdcf3dbec7f963b5c5f4d1..9f928f702bb19d6b7ab2d019cd7eb31acb950885 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.121 2008/01/01 19:46:00 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.122 2008/03/25 22:42:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -292,7 +292,7 @@ do_compile(FunctionCallInfo fcinfo,
 								  Anum_pg_proc_prosrc, &isnull);
 	if (isnull)
 		elog(ERROR, "null prosrc");
-	proc_source = DatumGetCString(DirectFunctionCall1(textout, prosrcdatum));
+	proc_source = TextDatumGetCString(prosrcdatum);
 	plpgsql_scanner_init(proc_source, functype);
 
 	plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 25702f2a8785aaa006c9c8b5242566cdcb816eb1..635a992820f87c8f4f7671e113a4035e225cde90 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.203 2008/03/25 19:26:54 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.204 2008/03/25 22:42:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -532,11 +532,11 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
 
 	var = (PLpgSQL_var *) (estate.datums[func->tg_op_varno]);
 	if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
-		var->value = DirectFunctionCall1(textin, CStringGetDatum("INSERT"));
+		var->value = CStringGetTextDatum("INSERT");
 	else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
-		var->value = DirectFunctionCall1(textin, CStringGetDatum("UPDATE"));
+		var->value = CStringGetTextDatum("UPDATE");
 	else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
-		var->value = DirectFunctionCall1(textin, CStringGetDatum("DELETE"));
+		var->value = CStringGetTextDatum("DELETE");
 	else
 		elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, or UPDATE");
 	var->isnull = false;
@@ -550,9 +550,9 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
 
 	var = (PLpgSQL_var *) (estate.datums[func->tg_when_varno]);
 	if (TRIGGER_FIRED_BEFORE(trigdata->tg_event))
-		var->value = DirectFunctionCall1(textin, CStringGetDatum("BEFORE"));
+		var->value = CStringGetTextDatum("BEFORE");
 	else if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
-		var->value = DirectFunctionCall1(textin, CStringGetDatum("AFTER"));
+		var->value = CStringGetTextDatum("AFTER");
 	else
 		elog(ERROR, "unrecognized trigger execution time: not BEFORE or AFTER");
 	var->isnull = false;
@@ -560,9 +560,9 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
 
 	var = (PLpgSQL_var *) (estate.datums[func->tg_level_varno]);
 	if (TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
-		var->value = DirectFunctionCall1(textin, CStringGetDatum("ROW"));
+		var->value = CStringGetTextDatum("ROW");
 	else if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
-		var->value = DirectFunctionCall1(textin, CStringGetDatum("STATEMENT"));
+		var->value = CStringGetTextDatum("STATEMENT");
 	else
 		elog(ERROR, "unrecognized trigger event type: not ROW or STATEMENT");
 	var->isnull = false;
@@ -611,8 +611,7 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
 	{
 		estate.trig_argv = palloc(sizeof(Datum) * estate.trig_nargs);
 		for (i = 0; i < trigdata->tg_trigger->tgnargs; i++)
-			estate.trig_argv[i] = DirectFunctionCall1(textin,
-						   CStringGetDatum(trigdata->tg_trigger->tgargs[i]));
+			estate.trig_argv[i] = CStringGetTextDatum(trigdata->tg_trigger->tgargs[i]);
 	}
 
 	estate.err_text = gettext_noop("during function entry");
@@ -1070,15 +1069,13 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
 
 					state_var = (PLpgSQL_var *)
 						estate->datums[block->exceptions->sqlstate_varno];
-					state_var->value = DirectFunctionCall1(textin,
-					   CStringGetDatum(unpack_sql_state(edata->sqlerrcode)));
+					state_var->value = CStringGetTextDatum(unpack_sql_state(edata->sqlerrcode));
 					state_var->freeval = true;
 					state_var->isnull = false;
 
 					errm_var = (PLpgSQL_var *)
 						estate->datums[block->exceptions->sqlerrm_varno];
-					errm_var->value = DirectFunctionCall1(textin,
-											CStringGetDatum(edata->message));
+					errm_var->value = CStringGetTextDatum(edata->message);
 					errm_var->freeval = true;
 					errm_var->isnull = false;
 
@@ -3017,7 +3014,7 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
 	curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
 	if (!curvar->isnull)
 	{
-		curname = DatumGetCString(DirectFunctionCall1(textout, curvar->value));
+		curname = TextDatumGetCString(curvar->value);
 		if (SPI_cursor_find(curname) != NULL)
 			ereport(ERROR,
 					(errcode(ERRCODE_DUPLICATE_CURSOR),
@@ -3090,7 +3087,7 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
 		 * ----------
 		 */
 		free_var(curvar);
-		curvar->value = DirectFunctionCall1(textin, CStringGetDatum(portal->name));
+		curvar->value = CStringGetTextDatum(portal->name);
 		curvar->isnull = false;
 		curvar->freeval = true;
 
@@ -3188,7 +3185,7 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
 	 * ----------
 	 */
 	free_var(curvar);
-	curvar->value = DirectFunctionCall1(textin, CStringGetDatum(portal->name));
+	curvar->value = CStringGetTextDatum(portal->name);
 	curvar->isnull = false;
 	curvar->freeval = true;
 
@@ -3222,7 +3219,7 @@ exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
 		ereport(ERROR,
 				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 				 errmsg("cursor variable \"%s\" is NULL", curvar->refname)));
-	curname = DatumGetCString(DirectFunctionCall1(textout, curvar->value));
+	curname = TextDatumGetCString(curvar->value);
 
 	portal = SPI_cursor_find(curname);
 	if (portal == NULL)
@@ -3318,7 +3315,7 @@ exec_stmt_close(PLpgSQL_execstate *estate, PLpgSQL_stmt_close *stmt)
 		ereport(ERROR,
 				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 				 errmsg("cursor variable \"%s\" is NULL", curvar->refname)));
-	curname = DatumGetCString(DirectFunctionCall1(textout, curvar->value));
+	curname = TextDatumGetCString(curvar->value);
 
 	portal = SPI_cursor_find(curname);
 	if (portal == NULL)
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index afbb3abeda8f50b129131d1ded06c9edba33a591..20177d62e1bb5d3a1ec58f8df6ef60a014776e49 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -1,7 +1,7 @@
 /**********************************************************************
  * plpython.c - python as a procedural language for PostgreSQL
  *
- *	$PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.106 2008/01/02 03:10:27 tgl Exp $
+ *	$PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.107 2008/03/25 22:42:45 tgl Exp $
  *
  *********************************************************************
  */
@@ -1298,7 +1298,7 @@ PLy_procedure_create(HeapTuple procTup, Oid tgreloid, char *key)
 
 			/* Fetch argument name */
 			if (proc->argnames)
-				proc->argnames[i] = PLy_strdup(DatumGetCString(DirectFunctionCall1(textout, elems[i])));
+				proc->argnames[i] = PLy_strdup(TextDatumGetCString(elems[i]));
 		}
 
 		/*
@@ -1308,8 +1308,7 @@ PLy_procedure_create(HeapTuple procTup, Oid tgreloid, char *key)
 									  Anum_pg_proc_prosrc, &isnull);
 		if (isnull)
 			elog(ERROR, "null prosrc");
-		procSource = DatumGetCString(DirectFunctionCall1(textout,
-														 prosrcdatum));
+		procSource = TextDatumGetCString(prosrcdatum);
 
 		PLy_procedure_compile(proc, procSource);
 
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 4b72b860bbc7e4d1e792462bc1d08b573954a0af..508ec301bf83f15615b777598665037c0ed01bd8 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -2,7 +2,7 @@
  * pltcl.c		- PostgreSQL support for Tcl as
  *				  procedural language (PL)
  *
- *	  $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.117 2007/11/15 21:14:46 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.118 2008/03/25 22:42:46 tgl Exp $
  *
  **********************************************************************/
 
@@ -1298,8 +1298,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid)
 									  Anum_pg_proc_prosrc, &isnull);
 		if (isnull)
 			elog(ERROR, "null prosrc");
-		proc_source = DatumGetCString(DirectFunctionCall1(textout,
-														  prosrcdatum));
+		proc_source = TextDatumGetCString(prosrcdatum);
 		UTF_BEGIN;
 		Tcl_DStringAppend(&proc_internal_body, UTF_E2U(proc_source), -1);
 		UTF_END;
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index 8f96382dfd62ada37cb2c76d550a2faa56ff2b74..c5ea947f84e3a6388d681d0fd02a10e917e40017 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -1,5 +1,5 @@
 /*
- * $PostgreSQL: pgsql/src/test/regress/regress.c,v 1.70 2007/03/15 23:12:07 tgl Exp $
+ * $PostgreSQL: pgsql/src/test/regress/regress.c,v 1.71 2008/03/25 22:42:46 tgl Exp $
  */
 
 #include "postgres.h"
@@ -556,16 +556,9 @@ ttdummy(PG_FUNCTION_ARGS)
 		return PointerGetDatum(NULL);
 	}
 
-	{
-		text	   *seqname = DatumGetTextP(DirectFunctionCall1(textin,
-											CStringGetDatum("ttdummy_seq")));
-
-		newoff = DirectFunctionCall1(nextval,
-									 PointerGetDatum(seqname));
-		/* nextval now returns int64; coerce down to int32 */
-		newoff = Int32GetDatum((int32) DatumGetInt64(newoff));
-		pfree(seqname);
-	}
+	newoff = DirectFunctionCall1(nextval, CStringGetTextDatum("ttdummy_seq"));
+	/* nextval now returns int64; coerce down to int32 */
+	newoff = Int32GetDatum((int32) DatumGetInt64(newoff));
 
 	/* Connect to SPI manager */
 	if ((ret = SPI_connect()) < 0)