--- fe-exec.c	Thu May  8 11:49:34 2003
+++ fe-exec.c.latest	Thu May  8 11:45:17 2003
@@ -180,6 +180,8 @@
 	return result;
 }
 
+#define VAL(CH) ((CH) - '0')
+
 /*
  *		PQunescapeBytea - converts the null terminated string representation
  *		of a bytea, strtext, into binary, filling a buffer. It returns a
@@ -187,101 +189,66 @@
  *		buffer in retbuflen. The pointer may subsequently be used as an
  *		argument to the function free(3). It is the reverse of PQescapeBytea.
  *
- *		The following transformations are reversed:
- *		'\0' == ASCII  0 == \000
- *		'\'' == ASCII 39 == \'
- *		'\\' == ASCII 92 == \\
+ *		The following transformations are made:
+ *		\'   == ASCII 39 == '
+ *		\\   == ASCII 92 == \
+ *		\ooo == a byte whose value = ooo (ooo is an octal number)
+ *		\x   == x (x is any character not matched by the above transformations)
  *
- *		States:
- *		0	normal		0->1->2->3->4
- *		1	\			   1->5
- *		2	\0			   1->6
- *		3	\00
- *		4	\000
- *		5	\'
- *		6	\\
  */
 unsigned char *
 PQunescapeBytea(unsigned char *strtext, size_t *retbuflen)
 {
-	size_t		buflen;
-	unsigned char *buffer,
-			   *sp,
-			   *bp;
-	unsigned int state = 0;
+	size_t strtextlen, buflen;
+	unsigned char *buffer, *tmpbuf;
+	int i, j, byte;
 
-	if (strtext == NULL)
+	if (strtext == NULL) {
 		return NULL;
-	buflen = strlen(strtext);	/* will shrink, also we discover if
-								 * strtext */
-	buffer = (unsigned char *) malloc(buflen);	/* isn't NULL terminated */
+	}
+
+	strtextlen = strlen(strtext);	/* will shrink, also we discover if
+									 * strtext isn't NULL terminated */
+	buffer = (unsigned char *)malloc(strtextlen);
 	if (buffer == NULL)
 		return NULL;
-	for (bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++)
+
+	for (i = j = buflen = 0; i < strtextlen;)
 	{
-		switch (state)
+		switch (strtext[i])
 		{
-			case 0:
-				if (*sp == '\\')
-					state = 1;
-				*bp = *sp;
-				break;
-			case 1:
-				if (*sp == '\'')	/* state=5 */
-				{				/* replace \' with 39 */
-					bp--;
-					*bp = '\'';
-					buflen--;
-					state = 0;
-				}
-				else if (*sp == '\\')	/* state=6 */
-				{				/* replace \\ with 92 */
-					bp--;
-					*bp = '\\';
-					buflen--;
-					state = 0;
-				}
+			case '\\':
+				i++;
+				if (strtext[i] == '\\')
+					buffer[j++] = strtext[i++];
 				else
 				{
-					if (isdigit(*sp))
-						state = 2;
-					else
-						state = 0;
-					*bp = *sp;
+					if ((isdigit(strtext[i]))   &&
+						(isdigit(strtext[i+1])) &&
+						(isdigit(strtext[i+2])))
+					{
+						byte = VAL(strtext[i++]);
+						byte = (byte << 3) + VAL(strtext[i++]);
+						buffer[j++] = (byte << 3) + VAL(strtext[i++]);
+					}
 				}
 				break;
-			case 2:
-				if (isdigit(*sp))
-					state = 3;
-				else
-					state = 0;
-				*bp = *sp;
-				break;
-			case 3:
-				if (isdigit(*sp))		/* state=4 */
-				{
-					int			v;
 
-					bp -= 3;
-					sscanf(sp - 2, "%03o", &v);
-					*bp = v;
-					buflen -= 3;
-					state = 0;
-				}
-				else
-				{
-					*bp = *sp;
-					state = 0;
-				}
-				break;
+			default:
+				buffer[j++] = strtext[i++];
 		}
 	}
-	buffer = realloc(buffer, buflen);
-	if (buffer == NULL)
-		return NULL;
+	buflen = j; /* buflen is the length of the unquoted data */
+	tmpbuf = realloc(buffer, buflen);
+
+	if (!tmpbuf)
+	{
+		free(buffer);
+		return 0;
+	}
 
 	*retbuflen = buflen;
-	return buffer;
+	return tmpbuf;
 }
 
 /* ----------------
