Index: src/backend/utils/adt/formatting.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v
retrieving revision 1.94
diff -c -c -r1.94 formatting.c
*** src/backend/utils/adt/formatting.c	27 Jul 2005 12:44:09 -0000	1.94
--- src/backend/utils/adt/formatting.c	17 Aug 2005 21:42:02 -0000
***************
*** 136,142 ****
  	const char *name;			/* keyword			*/
  	int			len;			/* keyword length		*/
  	int (*action) (int arg, char *inout,	/* action for keyword */
! 				   int suf, int flag,
  				   FormatNode *node, void *data);
  	int			id;				/* keyword id			*/
  	bool		isitdigit;		/* is expected output/input digit */
--- 136,142 ----
  	const char *name;			/* keyword			*/
  	int			len;			/* keyword length		*/
  	int (*action) (int arg, char *inout,	/* action for keyword */
! 				   int suf, bool is_to_char,
  				   FormatNode *node, void *data);
  	int			id;				/* keyword id			*/
  	bool		isitdigit;		/* is expected output/input digit */
***************
*** 231,239 ****
   * Flags & Options:
   * ----------
   */
- #define TO_CHAR		1
- #define FROM_CHAR	2
- 
  #define ONE_UPPER	1			/* Name */
  #define ALL_UPPER	2			/* NAME */
  #define ALL_LOWER	3			/* name */
--- 231,236 ----
***************
*** 250,260 ****
   * Flags for DCH version
   * ----------
   */
! static int	DCH_global_flag = 0;
! 
! #define DCH_F_FX	0x01
! 
! #define IS_FX		(DCH_global_flag & DCH_F_FX)
  
  
  /* ----------
--- 247,253 ----
   * Flags for DCH version
   * ----------
   */
! static bool	DCH_global_fx = false;
  
  
  /* ----------
***************
*** 440,448 ****
   *			KeyWords definition & action
   *****************************************************************************/
  
! static int	dch_global(int arg, char *inout, int suf, int flag, FormatNode *node, void *data);
! static int	dch_time(int arg, char *inout, int suf, int flag, FormatNode *node, void *data);
! static int	dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data);
  
  /* ----------
   * Suffixes:
--- 433,441 ----
   *			KeyWords definition & action
   *****************************************************************************/
  
! static int	dch_global(int arg, char *inout, int suf, bool is_to_char, FormatNode *node, void *data);
! static int	dch_time(int arg, char *inout, int suf, bool is_to_char, FormatNode *node, void *data);
! static int	dch_date(int arg, char *inout, int suf, bool is_to_char, FormatNode *node, void *data);
  
  /* ----------
   * Suffixes:
***************
*** 843,850 ****
   */
  typedef struct NUMProc
  {
! 	int			type;			/* FROM_CHAR (TO_NUMBER) or TO_CHAR */
! 
  	NUMDesc    *Num;			/* number description		*/
  
  	int			sign,			/* '-' or '+'			*/
--- 836,842 ----
   */
  typedef struct NUMProc
  {
! 	bool		is_to_char;
  	NUMDesc    *Num;			/* number description		*/
  
  	int			sign,			/* '-' or '+'			*/
***************
*** 883,889 ****
  static void NUMDesc_prepare(NUMDesc *num, FormatNode *n);
  static void parse_format(FormatNode *node, char *str, const KeyWord *kw,
  			 KeySuffix *suf, const int *index, int ver, NUMDesc *Num);
! static char *DCH_processor(FormatNode *node, char *inout, int flag, void *data);
  
  #ifdef DEBUG_TO_FROM_CHAR
  static void dump_index(const KeyWord *k, const int *index);
--- 875,881 ----
  static void NUMDesc_prepare(NUMDesc *num, FormatNode *n);
  static void parse_format(FormatNode *node, char *str, const KeyWord *kw,
  			 KeySuffix *suf, const int *index, int ver, NUMDesc *Num);
! static char *DCH_processor(FormatNode *node, char *inout, bool is_to_char, void *data);
  
  #ifdef DEBUG_TO_FROM_CHAR
  static void dump_index(const KeyWord *k, const int *index);
***************
*** 908,914 ****
  static void NUM_numpart_from_char(NUMProc *Np, int id, int plen);
  static void NUM_numpart_to_char(NUMProc *Np, int id);
  static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
! 			  int plen, int sign, int type);
  static DCHCacheEntry *DCH_cache_search(char *str);
  static DCHCacheEntry *DCH_cache_getnew(char *str);
  
--- 900,906 ----
  static void NUM_numpart_from_char(NUMProc *Np, int id, int plen);
  static void NUM_numpart_to_char(NUMProc *Np, int id);
  static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
! 			  int plen, int sign, bool is_to_char);
  static DCHCacheEntry *DCH_cache_search(char *str);
  static DCHCacheEntry *DCH_cache_getnew(char *str);
  
***************
*** 1298,1304 ****
   * ----------
   */
  static char *
! DCH_processor(FormatNode *node, char *inout, int flag, void *data)
  {
  	FormatNode *n;
  	char	   *s;
--- 1290,1296 ----
   * ----------
   */
  static char *
! DCH_processor(FormatNode *node, char *inout, bool is_to_char, void *data)
  {
  	FormatNode *n;
  	char	   *s;
***************
*** 1307,1317 ****
  	/*
  	 * Zeroing global flags
  	 */
! 	DCH_global_flag = 0;
  
  	for (n = node, s = inout; n->type != NODE_TYPE_END; n++)
  	{
! 		if (flag == FROM_CHAR && *s == '\0')
  
  			/*
  			 * The input string is shorter than format picture, so it's
--- 1299,1309 ----
  	/*
  	 * Zeroing global flags
  	 */
! 	DCH_global_fx = false;
  
  	for (n = node, s = inout; n->type != NODE_TYPE_END; n++)
  	{
! 		if (!is_to_char && *s == '\0')
  
  			/*
  			 * The input string is shorter than format picture, so it's
***************
*** 1329,1335 ****
  			/*
  			 * Call node action function
  			 */
! 			len = n->key->action(n->key->id, s, n->suffix, flag, n, data);
  			if (len > 0)
  				s += len;
  			else if (len == -1)
--- 1321,1327 ----
  			/*
  			 * Call node action function
  			 */
! 			len = n->key->action(n->key->id, s, n->suffix, is_to_char, n, data);
  			if (len > 0)
  				s += len;
  			else if (len == -1)
***************
*** 1341,1366 ****
  			/*
  			 * Remove to output char from input in TO_CHAR
  			 */
! 			if (flag == TO_CHAR)
  				*s = n->character;
- 
  			else
  			{
  				/*
  				 * Skip blank space in FROM_CHAR's input
  				 */
! 				if (isspace((unsigned char) n->character) && IS_FX == 0)
! 				{
  					while (*s != '\0' && isspace((unsigned char) *(s + 1)))
  						++s;
- 				}
  			}
  		}
! 
! 		++s;					/* ! */
  	}
  
! 	if (flag == TO_CHAR)
  		*s = '\0';
  	return inout;
  }
--- 1333,1354 ----
  			/*
  			 * Remove to output char from input in TO_CHAR
  			 */
! 			if (is_to_char)
  				*s = n->character;
  			else
  			{
  				/*
  				 * Skip blank space in FROM_CHAR's input
  				 */
! 				if (isspace((unsigned char) n->character) && !DCH_global_fx)
  					while (*s != '\0' && isspace((unsigned char) *(s + 1)))
  						++s;
  			}
  		}
! 		++s;
  	}
  
! 	if (is_to_char)
  		*s = '\0';
  	return inout;
  }
***************
*** 1630,1639 ****
   * ----------
   */
  static int
! dch_global(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
  {
  	if (arg == DCH_FX)
! 		DCH_global_flag |= DCH_F_FX;
  	return -1;
  }
  
--- 1618,1627 ----
   * ----------
   */
  static int
! dch_global(int arg, char *inout, int suf, bool is_to_char, FormatNode *node, void *data)
  {
  	if (arg == DCH_FX)
! 		DCH_global_fx = true;
  	return -1;
  }
  
***************
*** 1696,1709 ****
   * ----------
   */
  static int
! dch_time(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
  {
  	char	   *p_inout = inout;
  	struct pg_tm *tm = NULL;
  	TmFromChar *tmfc = NULL;
  	TmToChar   *tmtc = NULL;
  
! 	if (flag == TO_CHAR)
  	{
  		tmtc = (TmToChar *) data;
  		tm = tmtcTm(tmtc);
--- 1684,1697 ----
   * ----------
   */
  static int
! dch_time(int arg, char *inout, int suf, bool is_to_char, FormatNode *node, void *data)
  {
  	char	   *p_inout = inout;
  	struct pg_tm *tm = NULL;
  	TmFromChar *tmfc = NULL;
  	TmToChar   *tmtc = NULL;
  
! 	if (is_to_char)
  	{
  		tmtc = (TmToChar *) data;
  		tm = tmtcTm(tmtc);
***************
*** 1715,1727 ****
  	{
  		case DCH_A_M:
  		case DCH_P_M:
! 			if (flag == TO_CHAR)
  			{
  				strcpy(inout, ((tm->tm_hour > 11
  							  && tm->tm_hour < HOURS_PER_DAY) ? P_M_STR : A_M_STR));
  				return 3;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (strncmp(inout, P_M_STR, 4) == 0)
  					tmfc->pm = TRUE;
--- 1703,1715 ----
  	{
  		case DCH_A_M:
  		case DCH_P_M:
! 			if (is_to_char)
  			{
  				strcpy(inout, ((tm->tm_hour > 11
  							  && tm->tm_hour < HOURS_PER_DAY) ? P_M_STR : A_M_STR));
  				return 3;
  			}
! 			else
  			{
  				if (strncmp(inout, P_M_STR, 4) == 0)
  					tmfc->pm = TRUE;
***************
*** 1734,1746 ****
  			break;
  		case DCH_AM:
  		case DCH_PM:
! 			if (flag == TO_CHAR)
  			{
  				strcpy(inout, ((tm->tm_hour > 11
  								&& tm->tm_hour < HOURS_PER_DAY) ? PM_STR : AM_STR));
  				return 1;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (strncmp(inout, PM_STR, 2) == 0)
  					tmfc->pm = TRUE;
--- 1722,1734 ----
  			break;
  		case DCH_AM:
  		case DCH_PM:
! 			if (is_to_char)
  			{
  				strcpy(inout, ((tm->tm_hour > 11
  								&& tm->tm_hour < HOURS_PER_DAY) ? PM_STR : AM_STR));
  				return 1;
  			}
! 			else
  			{
  				if (strncmp(inout, PM_STR, 2) == 0)
  					tmfc->pm = TRUE;
***************
*** 1753,1765 ****
  			break;
  		case DCH_a_m:
  		case DCH_p_m:
! 			if (flag == TO_CHAR)
  			{
  				strcpy(inout, ((tm->tm_hour > 11
  							  && tm->tm_hour < HOURS_PER_DAY) ? p_m_STR : a_m_STR));
  				return 3;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (strncmp(inout, p_m_STR, 4) == 0)
  					tmfc->pm = TRUE;
--- 1741,1753 ----
  			break;
  		case DCH_a_m:
  		case DCH_p_m:
! 			if (is_to_char)
  			{
  				strcpy(inout, ((tm->tm_hour > 11
  							  && tm->tm_hour < HOURS_PER_DAY) ? p_m_STR : a_m_STR));
  				return 3;
  			}
! 			else
  			{
  				if (strncmp(inout, p_m_STR, 4) == 0)
  					tmfc->pm = TRUE;
***************
*** 1772,1784 ****
  			break;
  		case DCH_am:
  		case DCH_pm:
! 			if (flag == TO_CHAR)
  			{
  				strcpy(inout, ((tm->tm_hour > 11
  								&& tm->tm_hour < HOURS_PER_DAY) ? pm_STR : am_STR));
  				return 1;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (strncmp(inout, pm_STR, 2) == 0)
  					tmfc->pm = TRUE;
--- 1760,1772 ----
  			break;
  		case DCH_am:
  		case DCH_pm:
! 			if (is_to_char)
  			{
  				strcpy(inout, ((tm->tm_hour > 11
  								&& tm->tm_hour < HOURS_PER_DAY) ? pm_STR : am_STR));
  				return 1;
  			}
! 			else
  			{
  				if (strncmp(inout, pm_STR, 2) == 0)
  					tmfc->pm = TRUE;
***************
*** 1791,1797 ****
  			break;
  		case DCH_HH:
  		case DCH_HH12:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2,
  						tm->tm_hour == 0 ? 12 :
--- 1779,1785 ----
  			break;
  		case DCH_HH:
  		case DCH_HH12:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2,
  						tm->tm_hour == 0 ? 12 :
***************
*** 1804,1810 ****
  					return 1;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
--- 1792,1798 ----
  					return 1;
  
  			}
! 			else
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
***************
*** 1819,1825 ****
  			}
  			break;
  		case DCH_HH24:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_hour);
  				if (S_THth(suf))
--- 1807,1813 ----
  			}
  			break;
  		case DCH_HH24:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_hour);
  				if (S_THth(suf))
***************
*** 1830,1836 ****
  					return 1;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
--- 1818,1824 ----
  					return 1;
  
  			}
! 			else
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
***************
*** 1845,1851 ****
  			}
  			break;
  		case DCH_MI:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_min);
  				if (S_THth(suf))
--- 1833,1839 ----
  			}
  			break;
  		case DCH_MI:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_min);
  				if (S_THth(suf))
***************
*** 1856,1862 ****
  					return 1;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
--- 1844,1850 ----
  					return 1;
  
  			}
! 			else
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
***************
*** 1871,1877 ****
  			}
  			break;
  		case DCH_SS:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_sec);
  				if (S_THth(suf))
--- 1859,1865 ----
  			}
  			break;
  		case DCH_SS:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_sec);
  				if (S_THth(suf))
***************
*** 1882,1888 ****
  					return 1;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
--- 1870,1876 ----
  					return 1;
  
  			}
! 			else
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
***************
*** 1897,1903 ****
  			}
  			break;
  		case DCH_MS:			/* millisecond */
! 			if (flag == TO_CHAR)
  			{
  #ifdef HAVE_INT64_TIMESTAMP
  				sprintf(inout, "%03d", (int) (tmtc->fsec / INT64CONST(1000)));
--- 1885,1891 ----
  			}
  			break;
  		case DCH_MS:			/* millisecond */
! 			if (is_to_char)
  			{
  #ifdef HAVE_INT64_TIMESTAMP
  				sprintf(inout, "%03d", (int) (tmtc->fsec / INT64CONST(1000)));
***************
*** 1912,1918 ****
  					return 2;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				int			len,
  							x;
--- 1900,1906 ----
  					return 2;
  
  			}
! 			else
  			{
  				int			len,
  							x;
***************
*** 1944,1950 ****
  			}
  			break;
  		case DCH_US:			/* microsecond */
! 			if (flag == TO_CHAR)
  			{
  #ifdef HAVE_INT64_TIMESTAMP
  				sprintf(inout, "%06d", (int) tmtc->fsec);
--- 1932,1938 ----
  			}
  			break;
  		case DCH_US:			/* microsecond */
! 			if (is_to_char)
  			{
  #ifdef HAVE_INT64_TIMESTAMP
  				sprintf(inout, "%06d", (int) tmtc->fsec);
***************
*** 1958,1964 ****
  				else
  					return 5;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				int			len,
  							x;
--- 1946,1952 ----
  				else
  					return 5;
  			}
! 			else
  			{
  				int			len,
  							x;
***************
*** 1989,1995 ****
  			}
  			break;
  		case DCH_SSSS:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%d", tm->tm_hour * SECS_PER_HOUR +
  						tm->tm_min * SECS_PER_MINUTE +
--- 1977,1983 ----
  			}
  			break;
  		case DCH_SSSS:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%d", tm->tm_hour * SECS_PER_HOUR +
  						tm->tm_min * SECS_PER_MINUTE +
***************
*** 1998,2004 ****
  					str_numth(p_inout, inout, S_TH_TYPE(suf));
  				return strlen(p_inout) - 1;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
--- 1986,1992 ----
  					str_numth(p_inout, inout, S_TH_TYPE(suf));
  				return strlen(p_inout) - 1;
  			}
! 			else
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
***************
*** 2014,2020 ****
  			break;
  		case DCH_tz:
  		case DCH_TZ:
! 			if (flag == TO_CHAR && tmtcTzn(tmtc))
  			{
  				int			siz = strlen(tmtcTzn(tmtc));
  
--- 2002,2008 ----
  			break;
  		case DCH_tz:
  		case DCH_TZ:
! 			if (is_to_char && tmtcTzn(tmtc))
  			{
  				int			siz = strlen(tmtcTzn(tmtc));
  
***************
*** 2030,2036 ****
  				}
  				return siz - 1;
  			}
! 			else if (flag == FROM_CHAR)
  				ereport(ERROR,
  						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  						 errmsg("\"TZ\"/\"tz\" not supported")));
--- 2018,2024 ----
  				}
  				return siz - 1;
  			}
! 			else if (!is_to_char)
  				ereport(ERROR,
  						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  						 errmsg("\"TZ\"/\"tz\" not supported")));
***************
*** 2055,2061 ****
   * ----------
   */
  static int
! dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
  {
  	char		buff[DCH_CACHE_SIZE],
  				workbuff[32],
--- 2043,2049 ----
   * ----------
   */
  static int
! dch_date(int arg, char *inout, int suf, bool is_to_char, FormatNode *node, void *data)
  {
  	char		buff[DCH_CACHE_SIZE],
  				workbuff[32],
***************
*** 2066,2072 ****
  	TmFromChar *tmfc = NULL;
  	TmToChar   *tmtc = NULL;
  
! 	if (flag == TO_CHAR)
  	{
  		tmtc = (TmToChar *) data;
  		tm = tmtcTm(tmtc);
--- 2054,2060 ----
  	TmFromChar *tmfc = NULL;
  	TmToChar   *tmtc = NULL;
  
! 	if (is_to_char)
  	{
  		tmtc = (TmToChar *) data;
  		tm = tmtcTm(tmtc);
***************
*** 2081,2087 ****
  	 * or "january", all is before search convert to "first-upper". This
  	 * convention is used for MONTH, MON, DAY, DY
  	 */
! 	if (flag == FROM_CHAR)
  	{
  		if (arg == DCH_MONTH || arg == DCH_Month || arg == DCH_month)
  		{
--- 2069,2075 ----
  	 * or "january", all is before search convert to "first-upper". This
  	 * convention is used for MONTH, MON, DAY, DY
  	 */
! 	if (!is_to_char)
  	{
  		if (arg == DCH_MONTH || arg == DCH_Month || arg == DCH_month)
  		{
***************
*** 2121,2133 ****
  	{
  		case DCH_A_D:
  		case DCH_B_C:
! 			if (flag == TO_CHAR)
  			{
  				strcpy(inout, (tm->tm_year <= 0 ? B_C_STR : A_D_STR));
  				return 3;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (strncmp(inout, B_C_STR, 4) == 0)
  					tmfc->bc = TRUE;
--- 2109,2121 ----
  	{
  		case DCH_A_D:
  		case DCH_B_C:
! 			if (is_to_char)
  			{
  				strcpy(inout, (tm->tm_year <= 0 ? B_C_STR : A_D_STR));
  				return 3;
  
  			}
! 			else
  			{
  				if (strncmp(inout, B_C_STR, 4) == 0)
  					tmfc->bc = TRUE;
***************
*** 2136,2148 ****
  			break;
  		case DCH_AD:
  		case DCH_BC:
! 			if (flag == TO_CHAR)
  			{
  				strcpy(inout, (tm->tm_year <= 0 ? BC_STR : AD_STR));
  				return 1;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (strncmp(inout, BC_STR, 2) == 0)
  					tmfc->bc = TRUE;
--- 2124,2136 ----
  			break;
  		case DCH_AD:
  		case DCH_BC:
! 			if (is_to_char)
  			{
  				strcpy(inout, (tm->tm_year <= 0 ? BC_STR : AD_STR));
  				return 1;
  
  			}
! 			else
  			{
  				if (strncmp(inout, BC_STR, 2) == 0)
  					tmfc->bc = TRUE;
***************
*** 2151,2163 ****
  			break;
  		case DCH_a_d:
  		case DCH_b_c:
! 			if (flag == TO_CHAR)
  			{
  				strcpy(inout, (tm->tm_year <= 0 ? b_c_STR : a_d_STR));
  				return 3;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (strncmp(inout, b_c_STR, 4) == 0)
  					tmfc->bc = TRUE;
--- 2139,2151 ----
  			break;
  		case DCH_a_d:
  		case DCH_b_c:
! 			if (is_to_char)
  			{
  				strcpy(inout, (tm->tm_year <= 0 ? b_c_STR : a_d_STR));
  				return 3;
  
  			}
! 			else
  			{
  				if (strncmp(inout, b_c_STR, 4) == 0)
  					tmfc->bc = TRUE;
***************
*** 2166,2178 ****
  			break;
  		case DCH_ad:
  		case DCH_bc:
! 			if (flag == TO_CHAR)
  			{
  				strcpy(inout, (tm->tm_year <= 0 ? bc_STR : ad_STR));
  				return 1;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (strncmp(inout, bc_STR, 2) == 0)
  					tmfc->bc = TRUE;
--- 2154,2166 ----
  			break;
  		case DCH_ad:
  		case DCH_bc:
! 			if (is_to_char)
  			{
  				strcpy(inout, (tm->tm_year <= 0 ? bc_STR : ad_STR));
  				return 1;
  
  			}
! 			else
  			{
  				if (strncmp(inout, bc_STR, 2) == 0)
  					tmfc->bc = TRUE;
***************
*** 2229,2235 ****
  			return 2;
  
  		case DCH_MM:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_mon);
  				if (S_THth(suf))
--- 2217,2223 ----
  			return 2;
  
  		case DCH_MM:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_mon);
  				if (S_THth(suf))
***************
*** 2239,2245 ****
  				else
  					return 1;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
--- 2227,2233 ----
  				else
  					return 1;
  			}
! 			else
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
***************
*** 2291,2297 ****
  			return 2;
  
  		case DCH_DDD:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 3, tm->tm_yday);
  				if (S_THth(suf))
--- 2279,2285 ----
  			return 2;
  
  		case DCH_DDD:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 3, tm->tm_yday);
  				if (S_THth(suf))
***************
*** 2302,2308 ****
  					return 2;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
--- 2290,2296 ----
  					return 2;
  
  			}
! 			else
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
***************
*** 2317,2323 ****
  			}
  			break;
  		case DCH_DD:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_mday);
  				if (S_THth(suf))
--- 2305,2311 ----
  			}
  			break;
  		case DCH_DD:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_mday);
  				if (S_THth(suf))
***************
*** 2328,2334 ****
  					return 1;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
--- 2316,2322 ----
  					return 1;
  
  			}
! 			else
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
***************
*** 2343,2349 ****
  			}
  			break;
  		case DCH_D:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%d", tm->tm_wday + 1);
  				if (S_THth(suf))
--- 2331,2337 ----
  			}
  			break;
  		case DCH_D:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%d", tm->tm_wday + 1);
  				if (S_THth(suf))
***************
*** 2353,2366 ****
  				}
  				return 0;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				sscanf(inout, "%1d", &tmfc->d);
  				return 0 + SKIP_THth(suf);
  			}
  			break;
  		case DCH_WW:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2,
  						(tm->tm_yday - 1) / 7 + 1);
--- 2341,2354 ----
  				}
  				return 0;
  			}
! 			else
  			{
  				sscanf(inout, "%1d", &tmfc->d);
  				return 0 + SKIP_THth(suf);
  			}
  			break;
  		case DCH_WW:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2,
  						(tm->tm_yday - 1) / 7 + 1);
***************
*** 2372,2378 ****
  					return 1;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
--- 2360,2366 ----
  					return 1;
  
  			}
! 			else
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
***************
*** 2387,2393 ****
  			}
  			break;
  		case DCH_IW:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2,
  					 date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
--- 2375,2381 ----
  			}
  			break;
  		case DCH_IW:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2,
  					 date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
***************
*** 2398,2404 ****
  				else
  					return 1;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
--- 2386,2392 ----
  				else
  					return 1;
  			}
! 			else
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
***************
*** 2413,2419 ****
  			}
  			break;
  		case DCH_Q:
! 			if (flag == TO_CHAR)
  			{
  				if (!tm->tm_mon)
  					return -1;
--- 2401,2407 ----
  			}
  			break;
  		case DCH_Q:
! 			if (is_to_char)
  			{
  				if (!tm->tm_mon)
  					return -1;
***************
*** 2425,2438 ****
  				}
  				return 0;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				sscanf(inout, "%1d", &tmfc->q);
  				return 0 + SKIP_THth(suf);
  			}
  			break;
  		case DCH_CC:
! 			if (flag == TO_CHAR)
  			{
  				i = tm->tm_year / 100 + 1;
  				if (i <= 99 && i >= -99)
--- 2413,2426 ----
  				}
  				return 0;
  			}
! 			else
  			{
  				sscanf(inout, "%1d", &tmfc->q);
  				return 0 + SKIP_THth(suf);
  			}
  			break;
  		case DCH_CC:
! 			if (is_to_char)
  			{
  				i = tm->tm_year / 100 + 1;
  				if (i <= 99 && i >= -99)
***************
*** 2444,2450 ****
  				return strlen(p_inout) - 1;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
--- 2432,2438 ----
  				return strlen(p_inout) - 1;
  
  			}
! 			else
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
***************
*** 2459,2465 ****
  			}
  			break;
  		case DCH_Y_YYY:
! 			if (flag == TO_CHAR)
  			{
  				i = YEAR_ABS(tm->tm_year) / 1000;
  				sprintf(inout, "%d,%03d", i, YEAR_ABS(tm->tm_year) - (i * 1000));
--- 2447,2453 ----
  			}
  			break;
  		case DCH_Y_YYY:
! 			if (is_to_char)
  			{
  				i = YEAR_ABS(tm->tm_year) / 1000;
  				sprintf(inout, "%d,%03d", i, YEAR_ABS(tm->tm_year) - (i * 1000));
***************
*** 2467,2473 ****
  					str_numth(p_inout, inout, S_TH_TYPE(suf));
  				return strlen(p_inout) - 1;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				int			cc;
  
--- 2455,2461 ----
  					str_numth(p_inout, inout, S_TH_TYPE(suf));
  				return strlen(p_inout) - 1;
  			}
! 			else
  			{
  				int			cc;
  
***************
*** 2479,2485 ****
  			break;
  		case DCH_YYYY:
  		case DCH_IYYY:
! 			if (flag == TO_CHAR)
  			{
  				if (tm->tm_year <= 9999 && tm->tm_year >= -9998)
  					sprintf(inout, "%0*d",
--- 2467,2473 ----
  			break;
  		case DCH_YYYY:
  		case DCH_IYYY:
! 			if (is_to_char)
  			{
  				if (tm->tm_year <= 9999 && tm->tm_year >= -9998)
  					sprintf(inout, "%0*d",
***************
*** 2502,2508 ****
  					str_numth(p_inout, inout, S_TH_TYPE(suf));
  				return strlen(p_inout) - 1;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
--- 2490,2496 ----
  					str_numth(p_inout, inout, S_TH_TYPE(suf));
  				return strlen(p_inout) - 1;
  			}
! 			else
  			{
  				if (S_FM(suf) || is_next_separator(node))
  				{
***************
*** 2520,2526 ****
  			break;
  		case DCH_YYY:
  		case DCH_IYY:
! 			if (flag == TO_CHAR)
  			{
  				snprintf(buff, sizeof(buff), "%03d",
  						 arg == DCH_YYY ?
--- 2508,2514 ----
  			break;
  		case DCH_YYY:
  		case DCH_IYY:
! 			if (is_to_char)
  			{
  				snprintf(buff, sizeof(buff), "%03d",
  						 arg == DCH_YYY ?
***************
*** 2537,2543 ****
  				return 2;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				sscanf(inout, "%03d", &tmfc->year);
  
--- 2525,2531 ----
  				return 2;
  
  			}
! 			else
  			{
  				sscanf(inout, "%03d", &tmfc->year);
  
***************
*** 2555,2561 ****
  			break;
  		case DCH_YY:
  		case DCH_IY:
! 			if (flag == TO_CHAR)
  			{
  				snprintf(buff, sizeof(buff), "%02d",
  						 arg == DCH_YY ?
--- 2543,2549 ----
  			break;
  		case DCH_YY:
  		case DCH_IY:
! 			if (is_to_char)
  			{
  				snprintf(buff, sizeof(buff), "%02d",
  						 arg == DCH_YY ?
***************
*** 2572,2578 ****
  				return 1;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				sscanf(inout, "%02d", &tmfc->year);
  
--- 2560,2566 ----
  				return 1;
  
  			}
! 			else
  			{
  				sscanf(inout, "%02d", &tmfc->year);
  
***************
*** 2590,2596 ****
  			break;
  		case DCH_Y:
  		case DCH_I:
! 			if (flag == TO_CHAR)
  			{
  				snprintf(buff, sizeof(buff), "%1d",
  						 arg == DCH_Y ?
--- 2578,2584 ----
  			break;
  		case DCH_Y:
  		case DCH_I:
! 			if (is_to_char)
  			{
  				snprintf(buff, sizeof(buff), "%1d",
  						 arg == DCH_Y ?
***************
*** 2607,2613 ****
  				return 0;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				sscanf(inout, "%1d", &tmfc->year);
  
--- 2595,2601 ----
  				return 0;
  
  			}
! 			else
  			{
  				sscanf(inout, "%1d", &tmfc->year);
  
***************
*** 2620,2626 ****
  			}
  			break;
  		case DCH_RM:
! 			if (flag == TO_CHAR)
  			{
  				if (!tm->tm_mon)
  					return -1;
--- 2608,2614 ----
  			}
  			break;
  		case DCH_RM:
! 			if (is_to_char)
  			{
  				if (!tm->tm_mon)
  					return -1;
***************
*** 2632,2638 ****
  					return 3;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				tmfc->mm = 12 - seq_search(inout, rm_months_upper, ALL_UPPER, FULL_SIZ, &len);
  				CHECK_SEQ_SEARCH(len, "RM");
--- 2620,2626 ----
  					return 3;
  
  			}
! 			else
  			{
  				tmfc->mm = 12 - seq_search(inout, rm_months_upper, ALL_UPPER, FULL_SIZ, &len);
  				CHECK_SEQ_SEARCH(len, "RM");
***************
*** 2643,2649 ****
  			}
  			break;
  		case DCH_rm:
! 			if (flag == TO_CHAR)
  			{
  				if (!tm->tm_mon)
  					return -1;
--- 2631,2637 ----
  			}
  			break;
  		case DCH_rm:
! 			if (is_to_char)
  			{
  				if (!tm->tm_mon)
  					return -1;
***************
*** 2655,2661 ****
  					return 3;
  
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				tmfc->mm = 12 - seq_search(inout, rm_months_lower, ALL_LOWER, FULL_SIZ, &len);
  				CHECK_SEQ_SEARCH(len, "rm");
--- 2643,2649 ----
  					return 3;
  
  			}
! 			else
  			{
  				tmfc->mm = 12 - seq_search(inout, rm_months_lower, ALL_LOWER, FULL_SIZ, &len);
  				CHECK_SEQ_SEARCH(len, "rm");
***************
*** 2666,2672 ****
  			}
  			break;
  		case DCH_W:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%d", (tm->tm_mday - 1) / 7 + 1);
  				if (S_THth(suf))
--- 2654,2660 ----
  			}
  			break;
  		case DCH_W:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%d", (tm->tm_mday - 1) / 7 + 1);
  				if (S_THth(suf))
***************
*** 2676,2696 ****
  				}
  				return 0;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				sscanf(inout, "%1d", &tmfc->w);
  				return 0 + SKIP_THth(suf);
  			}
  			break;
  		case DCH_J:
! 			if (flag == TO_CHAR)
  			{
  				sprintf(inout, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
  				if (S_THth(suf))
  					str_numth(p_inout, inout, S_TH_TYPE(suf));
  				return strlen(p_inout) - 1;
  			}
! 			else if (flag == FROM_CHAR)
  			{
  				sscanf(inout, "%d", &tmfc->j);
  				return strdigits_len(inout) - 1 + SKIP_THth(suf);
--- 2664,2684 ----
  				}
  				return 0;
  			}
! 			else
  			{
  				sscanf(inout, "%1d", &tmfc->w);
  				return 0 + SKIP_THth(suf);
  			}
  			break;
  		case DCH_J:
! 			if (is_to_char)
  			{
  				sprintf(inout, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
  				if (S_THth(suf))
  					str_numth(p_inout, inout, S_TH_TYPE(suf));
  				return strlen(p_inout) - 1;
  			}
! 			else
  			{
  				sscanf(inout, "%d", &tmfc->j);
  				return strdigits_len(inout) - 1 + SKIP_THth(suf);
***************
*** 2857,2863 ****
  		format = ent->format;
  	}
  
! 	DCH_processor(format, result, TO_CHAR, (void *) tmtc);
  
  	if (!incache)
  		pfree(format);
--- 2845,2851 ----
  		format = ent->format;
  	}
  
! 	DCH_processor(format, result, true, (void *) tmtc);
  
  	if (!incache)
  		pfree(format);
***************
*** 3111,3117 ****
  		memcpy(date_str, VARDATA(date_txt), date_len);
  		*(date_str + date_len) = '\0';
  
! 		DCH_processor(format, date_str, FROM_CHAR, (void *) &tmfc);
  
  		pfree(date_str);
  		pfree(fmt_str);
--- 3099,3105 ----
  		memcpy(date_str, VARDATA(date_txt), date_len);
  		*(date_str + date_len) = '\0';
  
! 		DCH_processor(format, date_str, false, (void *) &tmfc);
  
  		pfree(date_str);
  		pfree(fmt_str);
***************
*** 4081,4087 ****
   */
  static char *
  NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
! 			  int plen, int sign, int type)
  {
  	FormatNode *n;
  	NUMProc		_Np,
--- 4069,4075 ----
   */
  static char *
  NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
! 			  int plen, int sign, bool is_to_char)
  {
  	FormatNode *n;
  	NUMProc		_Np,
***************
*** 4090,4096 ****
  	MemSet(Np, 0, sizeof(NUMProc));
  
  	Np->Num = Num;
! 	Np->type = type;
  	Np->number = number;
  	Np->inout = inout;
  	Np->last_relevant = NULL;
--- 4078,4084 ----
  	MemSet(Np, 0, sizeof(NUMProc));
  
  	Np->Num = Num;
! 	Np->is_to_char = is_to_char;
  	Np->number = number;
  	Np->inout = inout;
  	Np->last_relevant = NULL;
***************
*** 4106,4112 ****
  	 */
  	if (IS_ROMAN(Np->Num))
  	{
! 		if (Np->type == FROM_CHAR)
  			ereport(ERROR,
  					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  					 errmsg("\"RN\" not supported")));
--- 4094,4100 ----
  	 */
  	if (IS_ROMAN(Np->Num))
  	{
! 		if (!Np->is_to_char)
  			ereport(ERROR,
  					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  					 errmsg("\"RN\" not supported")));
***************
*** 4127,4135 ****
  	/*
  	 * Sign
  	 */
! 	if (type == FROM_CHAR)
! 		Np->sign = FALSE;
! 	else
  	{
  		Np->sign = sign;
  
--- 4115,4121 ----
  	/*
  	 * Sign
  	 */
! 	if (is_to_char)
  	{
  		Np->sign = sign;
  
***************
*** 4162,4174 ****
  				Np->Num->lsign = NUM_LSIGN_POST;
  		}
  	}
  
  	/*
  	 * Count
  	 */
  	Np->num_count = Np->Num->post + Np->Num->pre - 1;
  
! 	if (type == TO_CHAR)
  	{
  		Np->num_pre = plen;
  
--- 4148,4162 ----
  				Np->Num->lsign = NUM_LSIGN_POST;
  		}
  	}
+ 	else
+ 		Np->sign = FALSE;
  
  	/*
  	 * Count
  	 */
  	Np->num_count = Np->Num->post + Np->Num->pre - 1;
  
! 	if (is_to_char)
  	{
  		Np->num_pre = plen;
  
***************
*** 4224,4238 ****
  	/*
  	 * Processor direct cycle
  	 */
! 	if (Np->type == FROM_CHAR)
! 		Np->number_p = Np->number + 1;	/* first char is space for sign */
! 	else if (Np->type == TO_CHAR)
  		Np->number_p = Np->number;
  
  	for (n = node, Np->inout_p = Np->inout; n->type != NODE_TYPE_END; n++)
  	{
! 
! 		if (Np->type == FROM_CHAR)
  		{
  			/*
  			 * Check non-string inout end
--- 4212,4225 ----
  	/*
  	 * Processor direct cycle
  	 */
! 	if (Np->is_to_char)
  		Np->number_p = Np->number;
+ 	else
+ 		Np->number_p = Np->number + 1;	/* first char is space for sign */
  
  	for (n = node, Np->inout_p = Np->inout; n->type != NODE_TYPE_END; n++)
  	{
! 		if (!Np->is_to_char)
  		{
  			/*
  			 * Check non-string inout end
***************
*** 4261,4267 ****
  				case NUM_0:
  				case NUM_DEC:
  				case NUM_D:
! 					if (Np->type == TO_CHAR)
  					{
  						NUM_numpart_to_char(Np, n->key->id);
  						continue;		/* for() */
--- 4248,4254 ----
  				case NUM_0:
  				case NUM_DEC:
  				case NUM_D:
! 					if (Np->is_to_char)
  					{
  						NUM_numpart_to_char(Np, n->key->id);
  						continue;		/* for() */
***************
*** 4273,4279 ****
  					}
  
  				case NUM_COMMA:
! 					if (Np->type == TO_CHAR)
  					{
  						if (!Np->num_in)
  						{
--- 4260,4266 ----
  					}
  
  				case NUM_COMMA:
! 					if (Np->is_to_char)
  					{
  						if (!Np->num_in)
  						{
***************
*** 4284,4292 ****
  						}
  						else
  							*Np->inout_p = ',';
- 
  					}
! 					else if (Np->type == FROM_CHAR)
  					{
  						if (!Np->num_in)
  						{
--- 4271,4278 ----
  						}
  						else
  							*Np->inout_p = ',';
  					}
! 					else
  					{
  						if (!Np->num_in)
  						{
***************
*** 4297,4303 ****
  					break;
  
  				case NUM_G:
! 					if (Np->type == TO_CHAR)
  					{
  						if (!Np->num_in)
  						{
--- 4283,4289 ----
  					break;
  
  				case NUM_G:
! 					if (Np->is_to_char)
  					{
  						if (!Np->num_in)
  						{
***************
*** 4318,4324 ****
  						}
  
  					}
! 					else if (Np->type == FROM_CHAR)
  					{
  						if (!Np->num_in)
  						{
--- 4304,4310 ----
  						}
  
  					}
! 					else
  					{
  						if (!Np->num_in)
  						{
***************
*** 4330,4342 ****
  					break;
  
  				case NUM_L:
! 					if (Np->type == TO_CHAR)
  					{
  						strcpy(Np->inout_p, Np->L_currency_symbol);
  						Np->inout_p += strlen(Np->inout_p) - 1;
  
  					}
! 					else if (Np->type == FROM_CHAR)
  						Np->inout_p += strlen(Np->L_currency_symbol) - 1;
  					break;
  
--- 4316,4328 ----
  					break;
  
  				case NUM_L:
! 					if (Np->is_to_char)
  					{
  						strcpy(Np->inout_p, Np->L_currency_symbol);
  						Np->inout_p += strlen(Np->inout_p) - 1;
  
  					}
! 					else
  						Np->inout_p += strlen(Np->L_currency_symbol) - 1;
  					break;
  
***************
*** 4371,4377 ****
  						Np->sign == '-' || IS_DECIMAL(Np->Num))
  						continue;
  
! 					if (Np->type == TO_CHAR)
  						strcpy(Np->inout_p, get_th(Np->number, TH_LOWER));
  					Np->inout_p += 1;
  					break;
--- 4357,4363 ----
  						Np->sign == '-' || IS_DECIMAL(Np->Num))
  						continue;
  
! 					if (Np->is_to_char)
  						strcpy(Np->inout_p, get_th(Np->number, TH_LOWER));
  					Np->inout_p += 1;
  					break;
***************
*** 4381,4393 ****
  						Np->sign == '-' || IS_DECIMAL(Np->Num))
  						continue;
  
! 					if (Np->type == TO_CHAR)
  						strcpy(Np->inout_p, get_th(Np->number, TH_UPPER));
  					Np->inout_p += 1;
  					break;
  
  				case NUM_MI:
! 					if (Np->type == TO_CHAR)
  					{
  						if (Np->sign == '-')
  							*Np->inout_p = '-';
--- 4367,4379 ----
  						Np->sign == '-' || IS_DECIMAL(Np->Num))
  						continue;
  
! 					if (Np->is_to_char)
  						strcpy(Np->inout_p, get_th(Np->number, TH_UPPER));
  					Np->inout_p += 1;
  					break;
  
  				case NUM_MI:
! 					if (Np->is_to_char)
  					{
  						if (Np->sign == '-')
  							*Np->inout_p = '-';
***************
*** 4397,4403 ****
  							*Np->inout_p = ' ';
  
  					}
! 					else if (Np->type == FROM_CHAR)
  					{
  						if (*Np->inout_p == '-')
  							*Np->number = '-';
--- 4383,4389 ----
  							*Np->inout_p = ' ';
  
  					}
! 					else
  					{
  						if (*Np->inout_p == '-')
  							*Np->number = '-';
***************
*** 4405,4411 ****
  					break;
  
  				case NUM_PL:
! 					if (Np->type == TO_CHAR)
  					{
  						if (Np->sign == '+')
  							*Np->inout_p = '+';
--- 4391,4397 ----
  					break;
  
  				case NUM_PL:
! 					if (Np->is_to_char)
  					{
  						if (Np->sign == '+')
  							*Np->inout_p = '+';
***************
*** 4415,4421 ****
  							*Np->inout_p = ' ';
  
  					}
! 					else if (Np->type == FROM_CHAR)
  					{
  						if (*Np->inout_p == '+')
  							*Np->number = '+';
--- 4401,4407 ----
  							*Np->inout_p = ' ';
  
  					}
! 					else
  					{
  						if (*Np->inout_p == '+')
  							*Np->number = '+';
***************
*** 4423,4432 ****
  					break;
  
  				case NUM_SG:
! 					if (Np->type == TO_CHAR)
  						*Np->inout_p = Np->sign;
  
! 					else if (Np->type == FROM_CHAR)
  					{
  						if (*Np->inout_p == '-')
  							*Np->number = '-';
--- 4409,4418 ----
  					break;
  
  				case NUM_SG:
! 					if (Np->is_to_char)
  						*Np->inout_p = Np->sign;
  
! 					else
  					{
  						if (*Np->inout_p == '-')
  							*Np->number = '-';
***************
*** 4447,4465 ****
  			/*
  			 * Remove to output char from input in TO_CHAR
  			 */
! 			if (Np->type == TO_CHAR)
  				*Np->inout_p = n->character;
  		}
  		Np->inout_p++;
  	}
  
! 	if (Np->type == TO_CHAR)
  	{
  		*Np->inout_p = '\0';
  		return Np->inout;
- 
  	}
! 	else if (Np->type == FROM_CHAR)
  	{
  
  		if (*(Np->number_p - 1) == '.')
--- 4433,4450 ----
  			/*
  			 * Remove to output char from input in TO_CHAR
  			 */
! 			if (Np->is_to_char)
  				*Np->inout_p = n->character;
  		}
  		Np->inout_p++;
  	}
  
! 	if (Np->is_to_char)
  	{
  		*Np->inout_p = '\0';
  		return Np->inout;
  	}
! 	else
  	{
  
  		if (*(Np->number_p - 1) == '.')
***************
*** 4505,4511 ****
  #define NUM_TOCHAR_finish \
  do { \
  	NUM_processor(format, &Num, VARDATA(result),			\
! 		numstr, plen, sign, TO_CHAR);				\
  	pfree(orgnum);							\
  									\
  	if (shouldFree)							\
--- 4490,4496 ----
  #define NUM_TOCHAR_finish \
  do { \
  	NUM_processor(format, &Num, VARDATA(result),			\
! 		numstr, plen, sign, true);				\
  	pfree(orgnum);							\
  									\
  	if (shouldFree)							\
***************
*** 4557,4563 ****
  	numstr = (char *) palloc((len * NUM_MAX_ITEM_SIZ) + 1);
  
  	NUM_processor(format, &Num, VARDATA(value), numstr,
! 				  VARSIZE(value) - VARHDRSZ, 0, FROM_CHAR);
  
  	scale = Num.post;
  	precision = Max(0, Num.pre) + scale;
--- 4542,4548 ----
  	numstr = (char *) palloc((len * NUM_MAX_ITEM_SIZ) + 1);
  
  	NUM_processor(format, &Num, VARDATA(value), numstr,
! 				  VARSIZE(value) - VARHDRSZ, 0, false);
  
  	scale = Num.post;
  	precision = Max(0, Num.pre) + scale;
