diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index d4e5d553477a321ba431ff14256cae73af2caa23..4ee93ac04e1074d8dc7dc4d07264d9986f739386 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -411,17 +411,35 @@ Datum
 float8in(PG_FUNCTION_ARGS)
 {
 	char	   *num = PG_GETARG_CSTRING(0);
-	char	   *orig_num;
+
+	PG_RETURN_FLOAT8(float8in_internal(num, NULL, "double precision", num));
+}
+
+/*
+ * float8in_internal - guts of float8in()
+ *
+ * This is exposed for use by functions that want a reasonably
+ * platform-independent way of inputting doubles.  The behavior is
+ * essentially like strtod + ereport on error, but note the following
+ * differences:
+ * 1. Both leading and trailing whitespace are skipped.
+ * 2. If endptr_p is NULL, we throw error if there's trailing junk.
+ * Otherwise, it's up to the caller to complain about trailing junk.
+ * 3. In event of a syntax error, the report mentions the given type_name
+ * and prints orig_string as the input; this is meant to support use of
+ * this function with types such as "box" and "point", where what we are
+ * parsing here is just a substring of orig_string.
+ *
+ * "num" could validly be declared "const char *", but that results in an
+ * unreasonable amount of extra casting both here and in callers, so we don't.
+ */
+double
+float8in_internal(char *num, char **endptr_p,
+				  const char *type_name, const char *orig_string)
+{
 	double		val;
 	char	   *endptr;
 
-	/*
-	 * endptr points to the first character _after_ the sequence we recognized
-	 * as a valid floating point number. orig_num points to the original input
-	 * string.
-	 */
-	orig_num = num;
-
 	/* skip leading whitespace */
 	while (*num != '\0' && isspace((unsigned char) *num))
 		num++;
@@ -433,8 +451,8 @@ float8in(PG_FUNCTION_ARGS)
 	if (*num == '\0')
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-			 errmsg("invalid input syntax for type double precision: \"%s\"",
-					orig_num)));
+				 errmsg("invalid input syntax for type %s: \"%s\"",
+						type_name, orig_string)));
 
 	errno = 0;
 	val = strtod(num, &endptr);
@@ -497,18 +515,27 @@ float8in(PG_FUNCTION_ARGS)
 			 * precision).  We'd prefer not to throw error for that, so try to
 			 * detect whether it's a "real" out-of-range condition by checking
 			 * to see if the result is zero or huge.
+			 *
+			 * On error, we intentionally complain about double precision not
+			 * the given type name, and we print only the part of the string
+			 * that is the current number.
 			 */
 			if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL)
+			{
+				char	   *errnumber = pstrdup(num);
+
+				errnumber[endptr - num] = '\0';
 				ereport(ERROR,
 						(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				   errmsg("\"%s\" is out of range for type double precision",
-						  orig_num)));
+						  errnumber)));
+			}
 		}
 		else
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-			 errmsg("invalid input syntax for type double precision: \"%s\"",
-					orig_num)));
+					 errmsg("invalid input syntax for type %s: \"%s\"",
+							type_name, orig_string)));
 	}
 #ifdef HAVE_BUGGY_SOLARIS_STRTOD
 	else
@@ -527,16 +554,16 @@ float8in(PG_FUNCTION_ARGS)
 	while (*endptr != '\0' && isspace((unsigned char) *endptr))
 		endptr++;
 
-	/* if there is any junk left at the end of the string, bail out */
-	if (*endptr != '\0')
+	/* report stopping point if wanted, else complain if not end of string */
+	if (endptr_p)
+		*endptr_p = endptr;
+	else if (*endptr != '\0')
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-			 errmsg("invalid input syntax for type double precision: \"%s\"",
-					orig_num)));
+				 errmsg("invalid input syntax for type %s: \"%s\"",
+						type_name, orig_string)));
 
-	CHECKFLOATVAL(val, true, true);
-
-	PG_RETURN_FLOAT8(val);
+	return val;
 }
 
 /*
@@ -547,10 +574,24 @@ Datum
 float8out(PG_FUNCTION_ARGS)
 {
 	float8		num = PG_GETARG_FLOAT8(0);
+
+	PG_RETURN_CSTRING(float8out_internal(num));
+}
+
+/*
+ * float8out_internal - guts of float8out()
+ *
+ * This is exposed for use by functions that want a reasonably
+ * platform-independent way of outputting doubles.
+ * The result is always palloc'd.
+ */
+char *
+float8out_internal(double num)
+{
 	char	   *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);
 
 	if (isnan(num))
-		PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
+		return strcpy(ascii, "NaN");
 
 	switch (is_infinite(num))
 	{
@@ -571,7 +612,7 @@ float8out(PG_FUNCTION_ARGS)
 			}
 	}
 
-	PG_RETURN_CSTRING(ascii);
+	return ascii;
 }
 
 /*
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index b84673d64c19aac4f62fe352d365b7186b7aec4d..657bcee4fd40da81f3ae488cc8eed62159213253 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -57,12 +57,16 @@ static void make_bound_box(POLYGON *poly);
 static bool plist_same(int npts, Point *p1, Point *p2);
 static Point *point_construct(double x, double y);
 static Point *point_copy(Point *pt);
-static int	single_decode(char *str, float8 *x, char **ss);
-static int	single_encode(float8 x, char *str);
-static int	pair_decode(char *str, float8 *x, float8 *y, char **s);
-static int	pair_encode(float8 x, float8 y, char *str);
+static double single_decode(char *num, char **endptr_p,
+			  const char *type_name, const char *orig_string);
+static void single_encode(float8 x, StringInfo str);
+static void pair_decode(char *str, double *x, double *y, char **endptr_p,
+			const char *type_name, const char *orig_string);
+static void pair_encode(float8 x, float8 y, StringInfo str);
 static int	pair_count(char *s, char delim);
-static int	path_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point *p);
+static void path_decode(char *str, bool opentype, int npts, Point *p,
+			bool *isopen, char **endptr_p,
+			const char *type_name, const char *orig_string);
 static char *path_encode(enum path_delim path_delim, int npts, Point *pt);
 static void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2);
 static double box_ar(BOX *box);
@@ -91,10 +95,6 @@ static double dist_ppoly_internal(Point *pt, POLYGON *poly);
 #define LDELIM_C		'<'
 #define RDELIM_C		'>'
 
-/* Maximum number of characters printed by pair_encode() */
-/* ...+3+7 : 3 accounts for extra_float_digits max value */
-#define P_MAXLEN (2*(DBL_DIG+3+7)+1)
-
 
 /*
  * Geometric data types are composed of points.
@@ -121,195 +121,166 @@ static double dist_ppoly_internal(Point *pt, POLYGON *poly);
  *	and restore that order for text output - tgl 97/01/16
  */
 
-static int
-single_decode(char *str, float8 *x, char **s)
+static double
+single_decode(char *num, char **endptr_p,
+			  const char *type_name, const char *orig_string)
 {
-	char	   *cp;
-
-	if (!PointerIsValid(str))
-		return FALSE;
-
-	*x = strtod(str, &cp);
-
-#ifdef GEODEBUG
-	printf("single_decode- decoded first %d chars of \"%s\" to %g\n",
-		   (int) (cp - str), str, *x);
-#endif
-
-	if (s != NULL)
-	{
-		while (isspace((unsigned char) *cp))
-			cp++;
-		*s = cp;
-	}
-
-	return TRUE;
+	return float8in_internal(num, endptr_p, type_name, orig_string);
 }	/* single_decode() */
 
-static int
-single_encode(float8 x, char *str)
+static void
+single_encode(float8 x, StringInfo str)
 {
-	int			ndig = DBL_DIG + extra_float_digits;
+	char	   *xstr = float8out_internal(x);
 
-	if (ndig < 1)
-		ndig = 1;
-
-	sprintf(str, "%.*g", ndig, x);
-	return TRUE;
+	appendStringInfoString(str, xstr);
+	pfree(xstr);
 }	/* single_encode() */
 
-static int
-pair_decode(char *str, float8 *x, float8 *y, char **s)
+static void
+pair_decode(char *str, double *x, double *y, char **endptr_p,
+			const char *type_name, const char *orig_string)
 {
-	int			has_delim;
-	char	   *cp;
-
-	if (!PointerIsValid(str))
-		return FALSE;
+	bool		has_delim;
 
 	while (isspace((unsigned char) *str))
 		str++;
 	if ((has_delim = (*str == LDELIM)))
 		str++;
 
-	while (isspace((unsigned char) *str))
-		str++;
-	*x = strtod(str, &cp);
-	if (cp <= str)
-		return FALSE;
-	while (isspace((unsigned char) *cp))
-		cp++;
-	if (*cp++ != DELIM)
-		return FALSE;
-	while (isspace((unsigned char) *cp))
-		cp++;
-	*y = strtod(cp, &str);
-	if (str <= cp)
-		return FALSE;
-	while (isspace((unsigned char) *str))
-		str++;
+	*x = float8in_internal(str, &str, type_name, orig_string);
+
+	if (*str++ != DELIM)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+				 errmsg("invalid input syntax for type %s: \"%s\"",
+						type_name, orig_string)));
+
+	*y = float8in_internal(str, &str, type_name, orig_string);
+
 	if (has_delim)
 	{
-		if (*str != RDELIM)
-			return FALSE;
-		str++;
+		if (*str++ != RDELIM)
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+					 errmsg("invalid input syntax for type %s: \"%s\"",
+							type_name, orig_string)));
 		while (isspace((unsigned char) *str))
 			str++;
 	}
-	if (s != NULL)
-		*s = str;
 
-	return TRUE;
+	/* report stopping point if wanted, else complain if not end of string */
+	if (endptr_p)
+		*endptr_p = str;
+	else if (*str != '\0')
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+				 errmsg("invalid input syntax for type %s: \"%s\"",
+						type_name, orig_string)));
 }
 
-static int
-pair_encode(float8 x, float8 y, char *str)
+static void
+pair_encode(float8 x, float8 y, StringInfo str)
 {
-	int			ndig = DBL_DIG + extra_float_digits;
+	char	   *xstr = float8out_internal(x);
+	char	   *ystr = float8out_internal(y);
 
-	if (ndig < 1)
-		ndig = 1;
-
-	sprintf(str, "%.*g,%.*g", ndig, x, ndig, y);
-	return TRUE;
+	appendStringInfo(str, "%s,%s", xstr, ystr);
+	pfree(xstr);
+	pfree(ystr);
 }
 
-static int
-path_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point *p)
+static void
+path_decode(char *str, bool opentype, int npts, Point *p,
+			bool *isopen, char **endptr_p,
+			const char *type_name, const char *orig_string)
 {
 	int			depth = 0;
-	char	   *s,
-			   *cp;
+	char	   *cp;
 	int			i;
 
-	s = str;
-	while (isspace((unsigned char) *s))
-		s++;
-	if ((*isopen = (*s == LDELIM_EP)))
+	while (isspace((unsigned char) *str))
+		str++;
+	if ((*isopen = (*str == LDELIM_EP)))
 	{
 		/* no open delimiter allowed? */
 		if (!opentype)
-			return FALSE;
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+					 errmsg("invalid input syntax for type %s: \"%s\"",
+							type_name, orig_string)));
 		depth++;
-		s++;
-		while (isspace((unsigned char) *s))
-			s++;
-
+		str++;
 	}
-	else if (*s == LDELIM)
+	else if (*str == LDELIM)
 	{
-		cp = (s + 1);
+		cp = (str + 1);
 		while (isspace((unsigned char) *cp))
 			cp++;
 		if (*cp == LDELIM)
 		{
-#ifdef NOT_USED
-			/* nested delimiters with only one point? */
-			if (npts <= 1)
-				return FALSE;
-#endif
 			depth++;
-			s = cp;
+			str = cp;
 		}
-		else if (strrchr(s, LDELIM) == s)
+		else if (strrchr(str, LDELIM) == str)
 		{
 			depth++;
-			s = cp;
+			str = cp;
 		}
 	}
 
 	for (i = 0; i < npts; i++)
 	{
-		if (!pair_decode(s, &(p->x), &(p->y), &s))
-			return FALSE;
-
-		if (*s == DELIM)
-			s++;
+		pair_decode(str, &(p->x), &(p->y), &str, type_name, orig_string);
+		if (*str == DELIM)
+			str++;
 		p++;
 	}
 
+	while (isspace((unsigned char) *str))
+		str++;
 	while (depth > 0)
 	{
-		if ((*s == RDELIM)
-			|| ((*s == RDELIM_EP) && (*isopen) && (depth == 1)))
+		if ((*str == RDELIM)
+			|| ((*str == RDELIM_EP) && (*isopen) && (depth == 1)))
 		{
 			depth--;
-			s++;
-			while (isspace((unsigned char) *s))
-				s++;
+			str++;
+			while (isspace((unsigned char) *str))
+				str++;
 		}
 		else
-			return FALSE;
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+					 errmsg("invalid input syntax for type %s: \"%s\"",
+							type_name, orig_string)));
 	}
-	*ss = s;
 
-	return TRUE;
+	/* report stopping point if wanted, else complain if not end of string */
+	if (endptr_p)
+		*endptr_p = str;
+	else if (*str != '\0')
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+				 errmsg("invalid input syntax for type %s: \"%s\"",
+						type_name, orig_string)));
 }	/* path_decode() */
 
 static char *
 path_encode(enum path_delim path_delim, int npts, Point *pt)
 {
-	int			size = npts * (P_MAXLEN + 3) + 2;
-	char	   *result;
-	char	   *cp;
+	StringInfoData str;
 	int			i;
 
-	/* Check for integer overflow */
-	if ((size - 2) / npts != (P_MAXLEN + 3))
-		ereport(ERROR,
-				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
-				 errmsg("too many points requested")));
-
-	result = palloc(size);
+	initStringInfo(&str);
 
-	cp = result;
 	switch (path_delim)
 	{
 		case PATH_CLOSED:
-			*cp++ = LDELIM;
+			appendStringInfoChar(&str, LDELIM);
 			break;
 		case PATH_OPEN:
-			*cp++ = LDELIM_EP;
+			appendStringInfoChar(&str, LDELIM_EP);
 			break;
 		case PATH_NONE:
 			break;
@@ -317,32 +288,27 @@ path_encode(enum path_delim path_delim, int npts, Point *pt)
 
 	for (i = 0; i < npts; i++)
 	{
-		*cp++ = LDELIM;
-		if (!pair_encode(pt->x, pt->y, cp))
-			ereport(ERROR,
-					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-					 errmsg("could not format \"path\" value")));
-
-		cp += strlen(cp);
-		*cp++ = RDELIM;
-		*cp++ = DELIM;
+		if (i > 0)
+			appendStringInfoChar(&str, DELIM);
+		appendStringInfoChar(&str, LDELIM);
+		pair_encode(pt->x, pt->y, &str);
+		appendStringInfoChar(&str, RDELIM);
 		pt++;
 	}
-	cp--;
+
 	switch (path_delim)
 	{
 		case PATH_CLOSED:
-			*cp++ = RDELIM;
+			appendStringInfoChar(&str, RDELIM);
 			break;
 		case PATH_OPEN:
-			*cp++ = RDELIM_EP;
+			appendStringInfoChar(&str, RDELIM_EP);
 			break;
 		case PATH_NONE:
 			break;
 	}
-	*cp = '\0';
 
-	return result;
+	return str.data;
 }	/* path_encode() */
 
 /*-------------------------------------------------------------
@@ -387,16 +353,11 @@ box_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	BOX		   *box = (BOX *) palloc(sizeof(BOX));
-	int			isopen;
-	char	   *s;
+	bool		isopen;
 	double		x,
 				y;
 
-	if ((!path_decode(FALSE, 2, str, &isopen, &s, &(box->high)))
-		|| (*s != '\0'))
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-				 errmsg("invalid input syntax for type box: \"%s\"", str)));
+	path_decode(str, false, 2, &(box->high), &isopen, NULL, "box", str);
 
 	/* reorder corners if necessary... */
 	if (box->high.x < box->low.x)
@@ -935,43 +896,22 @@ box_diagonal(PG_FUNCTION_ARGS)
  ***********************************************************************/
 
 static bool
-line_decode(const char *str, LINE *line)
+line_decode(char *s, const char *str, LINE *line)
 {
-	char	   *tail;
-
-	while (isspace((unsigned char) *str))
-		str++;
-	if (*str++ != '{')
-		return false;
-	line->A = strtod(str, &tail);
-	if (tail <= str)
-		return false;
-	str = tail;
-	while (isspace((unsigned char) *str))
-		str++;
-	if (*str++ != DELIM)
-		return false;
-	line->B = strtod(str, &tail);
-	if (tail <= str)
+	/* s was already advanced over leading '{' */
+	line->A = single_decode(s, &s, "line", str);
+	if (*s++ != DELIM)
 		return false;
-	str = tail;
-	while (isspace((unsigned char) *str))
-		str++;
-	if (*str++ != DELIM)
+	line->B = single_decode(s, &s, "line", str);
+	if (*s++ != DELIM)
 		return false;
-	line->C = strtod(str, &tail);
-	if (tail <= str)
-		return false;
-	str = tail;
-	while (isspace((unsigned char) *str))
-		str++;
-	if (*str++ != '}')
+	line->C = single_decode(s, &s, "line", str);
+	if (*s++ != '}')
 		return false;
-	while (isspace((unsigned char) *str))
-		str++;
-	if (*str)
+	while (isspace((unsigned char) *s))
+		s++;
+	if (*s != '\0')
 		return false;
-
 	return true;
 }
 
@@ -979,33 +919,35 @@ Datum
 line_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
-	LINE	   *line;
+	LINE	   *line = (LINE *) palloc(sizeof(LINE));
 	LSEG		lseg;
-	int			isopen;
+	bool		isopen;
 	char	   *s;
 
-	line = (LINE *) palloc(sizeof(LINE));
-
-	if (path_decode(TRUE, 2, str, &isopen, &s, &(lseg.p[0])) && *s == '\0')
+	s = str;
+	while (isspace((unsigned char) *s))
+		s++;
+	if (*s == '{')
 	{
-		if (FPeq(lseg.p[0].x, lseg.p[1].x) && FPeq(lseg.p[0].y, lseg.p[1].y))
+		if (!line_decode(s + 1, str, line))
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-					 errmsg("invalid line specification: must be two distinct points")));
-
-		line_construct_pts(line, &lseg.p[0], &lseg.p[1]);
-	}
-	else if (line_decode(str, line))
-	{
+					 errmsg("invalid input syntax for type %s: \"%s\"",
+							"line", str)));
 		if (FPzero(line->A) && FPzero(line->B))
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid line specification: A and B cannot both be zero")));
 	}
 	else
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-				 errmsg("invalid input syntax for type line: \"%s\"", str)));
+	{
+		path_decode(s, true, 2, &(lseg.p[0]), &isopen, NULL, "line", str);
+		if (FPeq(lseg.p[0].x, lseg.p[1].x) && FPeq(lseg.p[0].y, lseg.p[1].y))
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+					 errmsg("invalid line specification: must be two distinct points")));
+		line_construct_pts(line, &lseg.p[0], &lseg.p[1]);
+	}
 
 	PG_RETURN_LINE_P(line);
 }
@@ -1015,12 +957,11 @@ Datum
 line_out(PG_FUNCTION_ARGS)
 {
 	LINE	   *line = PG_GETARG_LINE_P(0);
-	int			ndig = DBL_DIG + extra_float_digits;
+	char	   *astr = float8out_internal(line->A);
+	char	   *bstr = float8out_internal(line->B);
+	char	   *cstr = float8out_internal(line->C);
 
-	if (ndig < 1)
-		ndig = 1;
-
-	PG_RETURN_CSTRING(psprintf("{%.*g,%.*g,%.*g}", ndig, line->A, ndig, line->B, ndig, line->C));
+	PG_RETURN_CSTRING(psprintf("{%s,%s,%s}", astr, bstr, cstr));
 }
 
 /*
@@ -1367,7 +1308,7 @@ path_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	PATH	   *path;
-	int			isopen;
+	bool		isopen;
 	char	   *s;
 	int			npts;
 	int			size;
@@ -1377,7 +1318,8 @@ path_in(PG_FUNCTION_ARGS)
 	if ((npts = pair_count(str, ',')) <= 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-				 errmsg("invalid input syntax for type path: \"%s\"", str)));
+				 errmsg("invalid input syntax for type %s: \"%s\"",
+						"path", str)));
 
 	s = str;
 	while (isspace((unsigned char) *s))
@@ -1404,11 +1346,23 @@ path_in(PG_FUNCTION_ARGS)
 	SET_VARSIZE(path, size);
 	path->npts = npts;
 
-	if ((!path_decode(TRUE, npts, s, &isopen, &s, &(path->p[0])))
-	&& (!((depth == 0) && (*s == '\0'))) && !((depth >= 1) && (*s == RDELIM)))
+	path_decode(s, true, npts, &(path->p[0]), &isopen, &s, "path", str);
+
+	if (depth >= 1)
+	{
+		if (*s++ != RDELIM)
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+					 errmsg("invalid input syntax for type %s: \"%s\"",
+							"path", str)));
+		while (isspace((unsigned char) *s))
+			s++;
+	}
+	if (*s != '\0')
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-				 errmsg("invalid input syntax for type path: \"%s\"", str)));
+				 errmsg("invalid input syntax for type %s: \"%s\"",
+						"path", str)));
 
 	path->closed = (!isopen);
 	/* prevent instability in unused pad bytes */
@@ -1782,21 +1736,9 @@ Datum
 point_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
-	Point	   *point;
-	double		x,
-				y;
-	char	   *s;
-
-	if (!pair_decode(str, &x, &y, &s) || (*s != '\0'))
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-				 errmsg("invalid input syntax for type point: \"%s\"", str)));
-
-	point = (Point *) palloc(sizeof(Point));
-
-	point->x = x;
-	point->y = y;
+	Point	   *point = (Point *) palloc(sizeof(Point));
 
+	pair_decode(str, &point->x, &point->y, NULL, "point", str);
 	PG_RETURN_POINT_P(point);
 }
 
@@ -2008,18 +1950,10 @@ Datum
 lseg_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
-	LSEG	   *lseg;
-	int			isopen;
-	char	   *s;
-
-	lseg = (LSEG *) palloc(sizeof(LSEG));
-
-	if ((!path_decode(TRUE, 2, str, &isopen, &s, &(lseg->p[0])))
-		|| (*s != '\0'))
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-				 errmsg("invalid input syntax for type lseg: \"%s\"", str)));
+	LSEG	   *lseg = (LSEG *) palloc(sizeof(LSEG));
+	bool		isopen;
 
+	path_decode(str, true, 2, &(lseg->p[0]), &isopen, NULL, "lseg", str);
 	PG_RETURN_LSEG_P(lseg);
 }
 
@@ -3480,13 +3414,13 @@ poly_in(PG_FUNCTION_ARGS)
 	int			npts;
 	int			size;
 	int			base_size;
-	int			isopen;
-	char	   *s;
+	bool		isopen;
 
 	if ((npts = pair_count(str, ',')) <= 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-			  errmsg("invalid input syntax for type polygon: \"%s\"", str)));
+				 errmsg("invalid input syntax for type %s: \"%s\"",
+						"polygon", str)));
 
 	base_size = sizeof(poly->p[0]) * npts;
 	size = offsetof(POLYGON, p) +base_size;
@@ -3502,11 +3436,7 @@ poly_in(PG_FUNCTION_ARGS)
 	SET_VARSIZE(poly, size);
 	poly->npts = npts;
 
-	if ((!path_decode(FALSE, npts, str, &isopen, &s, &(poly->p[0])))
-		|| (*s != '\0'))
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-			  errmsg("invalid input syntax for type polygon: \"%s\"", str)));
+	path_decode(str, false, npts, &(poly->p[0]), &isopen, NULL, "polygon", str);
 
 	make_bound_box(poly);
 
@@ -4595,13 +4525,11 @@ Datum
 circle_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
-	CIRCLE	   *circle;
+	CIRCLE	   *circle = (CIRCLE *) palloc(sizeof(CIRCLE));
 	char	   *s,
 			   *cp;
 	int			depth = 0;
 
-	circle = (CIRCLE *) palloc(sizeof(CIRCLE));
-
 	s = str;
 	while (isspace((unsigned char) *s))
 		s++;
@@ -4615,20 +4543,17 @@ circle_in(PG_FUNCTION_ARGS)
 			s = cp;
 	}
 
-	if (!pair_decode(s, &circle->center.x, &circle->center.y, &s))
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-			   errmsg("invalid input syntax for type circle: \"%s\"", str)));
+	pair_decode(s, &circle->center.x, &circle->center.y, &s, "circle", str);
 
 	if (*s == DELIM)
 		s++;
-	while (isspace((unsigned char) *s))
-		s++;
 
-	if ((!single_decode(s, &circle->radius, &s)) || (circle->radius < 0))
+	circle->radius = single_decode(s, &s, "circle", str);
+	if (circle->radius < 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-			   errmsg("invalid input syntax for type circle: \"%s\"", str)));
+				 errmsg("invalid input syntax for type %s: \"%s\"",
+						"circle", str)));
 
 	while (depth > 0)
 	{
@@ -4643,13 +4568,15 @@ circle_in(PG_FUNCTION_ARGS)
 		else
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-			   errmsg("invalid input syntax for type circle: \"%s\"", str)));
+					 errmsg("invalid input syntax for type %s: \"%s\"",
+							"circle", str)));
 	}
 
 	if (*s != '\0')
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-			   errmsg("invalid input syntax for type circle: \"%s\"", str)));
+				 errmsg("invalid input syntax for type %s: \"%s\"",
+						"circle", str)));
 
 	PG_RETURN_CIRCLE_P(circle);
 }
@@ -4660,32 +4587,19 @@ Datum
 circle_out(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
-	char	   *result;
-	char	   *cp;
-
-	result = palloc(2 * P_MAXLEN + 6);
+	StringInfoData str;
 
-	cp = result;
-	*cp++ = LDELIM_C;
-	*cp++ = LDELIM;
-	if (!pair_encode(circle->center.x, circle->center.y, cp))
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("could not format \"circle\" value")));
-
-	cp += strlen(cp);
-	*cp++ = RDELIM;
-	*cp++ = DELIM;
-	if (!single_encode(circle->radius, cp))
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("could not format \"circle\" value")));
+	initStringInfo(&str);
 
-	cp += strlen(cp);
-	*cp++ = RDELIM_C;
-	*cp = '\0';
+	appendStringInfoChar(&str, LDELIM_C);
+	appendStringInfoChar(&str, LDELIM);
+	pair_encode(circle->center.x, circle->center.y, &str);
+	appendStringInfoChar(&str, RDELIM);
+	appendStringInfoChar(&str, DELIM);
+	single_encode(circle->radius, &str);
+	appendStringInfoChar(&str, RDELIM_C);
 
-	PG_RETURN_CSTRING(result);
+	PG_RETURN_CSTRING(str.data);
 }
 
 /*
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 206288da8100699ca07de94f15084e70433e8643..d5c4b01ada42468bfe83b762771083c8ff4a54ce 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -343,6 +343,9 @@ extern float get_float4_infinity(void);
 extern double get_float8_nan(void);
 extern float get_float4_nan(void);
 extern int	is_infinite(double val);
+extern double float8in_internal(char *num, char **endptr_p,
+				  const char *type_name, const char *orig_string);
+extern char *float8out_internal(double num);
 
 extern Datum float4in(PG_FUNCTION_ARGS);
 extern Datum float4out(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/box.out b/src/test/regress/expected/box.out
index 300190f762d875a50de7b23c0e5c495b932e8de4..7e251a3a56981552490a1235227a5db6afc8db00 100644
--- a/src/test/regress/expected/box.out
+++ b/src/test/regress/expected/box.out
@@ -232,15 +232,15 @@ INSERT INTO box_temp
 		   ('(-infinity,-infinity)(infinity,infinity)');
 SET enable_seqscan = false;
 SELECT * FROM box_temp WHERE f1 << '(10,20),(30,40)';
-        f1        
-------------------
+             f1             
+----------------------------
  (2,2),(1,1)
  (4,4),(2,2)
  (6,6),(3,3)
  (8,8),(4,4)
  (-0,100),(0,0)
- (0,inf),(0,100)
- (0,inf),(-inf,0)
+ (0,Infinity),(0,100)
+ (0,Infinity),(-Infinity,0)
 (7 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 << '(10,20),(30,40)';
@@ -251,16 +251,16 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 << '(10,20),(30,40)';
 (2 rows)
 
 SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)';
-        f1        
-------------------
+             f1             
+----------------------------
  (2,2),(1,1)
  (4,4),(2,2)
  (6,6),(3,3)
  (8,8),(4,4)
  (10,10),(5,5)
  (-0,100),(0,0)
- (0,inf),(0,100)
- (0,inf),(-inf,0)
+ (0,Infinity),(0,100)
+ (0,Infinity),(-Infinity,0)
 (8 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)';
@@ -271,8 +271,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)';
 (2 rows)
 
 SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)';
-          f1           
------------------------
+                    f1                     
+-------------------------------------------
  (20,20),(10,10)
  (22,22),(11,11)
  (24,24),(12,12)
@@ -289,7 +289,7 @@ SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)';
  (46,46),(23,23)
  (48,48),(24,24)
  (50,50),(25,25)
- (inf,inf),(-inf,-inf)
+ (Infinity,Infinity),(-Infinity,-Infinity)
 (17 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)';
@@ -375,10 +375,10 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &<| '(10,4.3333334),(5,1)';
 (2 rows)
 
 SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49.99)';
-        f1         
--------------------
+          f1          
+----------------------
  (100,100),(50,50)
- (0,inf),(0,100)
+ (0,Infinity),(0,100)
 (2 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49.99)';
@@ -389,8 +389,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49
 (2 rows)
 
 SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
-        f1         
--------------------
+          f1          
+----------------------
  (82,82),(41,41)
  (84,84),(42,42)
  (86,86),(43,43)
@@ -401,7 +401,7 @@ SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
  (96,96),(48,48)
  (98,98),(49,49)
  (100,100),(50,50)
- (0,inf),(0,100)
+ (0,Infinity),(0,100)
 (11 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
@@ -412,12 +412,12 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
 (2 rows)
 
 SELECT * FROM box_temp WHERE f1 @> '(10,11),(15,16)';
-          f1           
------------------------
+                    f1                     
+-------------------------------------------
  (16,16),(8,8)
  (18,18),(9,9)
  (20,20),(10,10)
- (inf,inf),(-inf,-inf)
+ (Infinity,Infinity),(-Infinity,-Infinity)
 (4 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 @> '(10,11),(15,15)';