Index: src/backend/utils/adt/formatting.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/utils/adt/formatting.c,v
retrieving revision 1.54
diff -c -r1.54 formatting.c
*** src/backend/utils/adt/formatting.c	4 Sep 2002 20:31:27 -0000	1.54
--- src/backend/utils/adt/formatting.c	18 Sep 2002 23:08:59 -0000
***************
*** 4,16 ****
   * $Header: /var/lib/cvs/pgsql-server/src/backend/utils/adt/formatting.c,v 1.54 2002/09/04 20:31:27 momjian Exp $
   *
   *
!  *	 Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
   *
   *
   *	 TO_CHAR(); TO_TIMESTAMP(); TO_DATE(); TO_NUMBER();
   *
   *	 The PostgreSQL routines for a timestamp/int/float/numeric formatting,
!  *	 inspire with Oracle TO_CHAR() / TO_DATE() / TO_NUMBER() routines.
   *
   *
   *	 Cache & Memory:
--- 4,16 ----
   * $Header: /var/lib/cvs/pgsql-server/src/backend/utils/adt/formatting.c,v 1.54 2002/09/04 20:31:27 momjian Exp $
   *
   *
!  *	 Portions Copyright (c) 1999-2002, PostgreSQL Global Development Group
   *
   *
   *	 TO_CHAR(); TO_TIMESTAMP(); TO_DATE(); TO_NUMBER();
   *
   *	 The PostgreSQL routines for a timestamp/int/float/numeric formatting,
!  *	 inspired by the Oracle TO_CHAR() / TO_DATE() / TO_NUMBER() routines.
   *
   *
   *	 Cache & Memory:
***************
*** 881,887 ****
  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);
  static char *fill_str(char *str, int c, int max);
! static FormatNode *NUM_cache(int len, NUMDesc *Num, char *pars_str, int *flag);
  static char *int_to_roman(int number);
  static void NUM_prepare_locale(NUMProc *Np);
  static char *get_last_relevant_decnum(char *num);
--- 881,887 ----
  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);
  static char *fill_str(char *str, int c, int max);
! static FormatNode *NUM_cache(int len, NUMDesc *Num, char *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);
***************
*** 899,905 ****
  
  /* ----------
   * Fast sequential search, use index for data selection which
!  * go to seq. cycle (it is very fast for non-wanted strings)
   * (can't be used binary search in format parsing)
   * ----------
   */
--- 899,905 ----
  
  /* ----------
   * Fast sequential search, use index for data selection which
!  * go to seq. cycle (it is very fast for unwanted strings)
   * (can't be used binary search in format parsing)
   * ----------
   */
***************
*** 957,963 ****
  
  	switch (n->key->id)
  	{
- 
  		case NUM_9:
  			if (IS_BRACKET(num))
  			{
--- 957,962 ----
***************
*** 1408,1414 ****
  }
  
  /* ----------
!  * Convert string to upper-string
   * ----------
   */
  static char *
--- 1407,1413 ----
  }
  
  /* ----------
!  * Convert string to upper-string. Input string is modified in place.
   * ----------
   */
  static char *
***************
*** 1416,1421 ****
--- 1415,1423 ----
  {
  	char	   *p_buff = buff;
  
+ 	if (!buff)
+ 		return NULL;
+ 
  	while (*p_buff)
  	{
  		*p_buff = toupper((unsigned char) *p_buff);
***************
*** 1425,1431 ****
  }
  
  /* ----------
!  * Convert string to lower-string
   * ----------
   */
  static char *
--- 1427,1433 ----
  }
  
  /* ----------
!  * Convert string to lower-string. Input string is modified in place.
   * ----------
   */
  static char *
***************
*** 1433,1438 ****
--- 1435,1443 ----
  {
  	char	   *p_buff = buff;
  
+ 	if (!buff)
+ 		return NULL;
+ 
  	while (*p_buff)
  	{
  		*p_buff = tolower((unsigned char) *p_buff);
***************
*** 2422,2428 ****
  		case DCH_YYY:
  			if (flag == TO_CHAR)
  			{
! 				sprintf(buff, "%03d", YEAR_ABS(tm->tm_year));
  				i = strlen(buff);
  				strcpy(inout, buff + (i - 3));
  				if (S_THth(suf))
--- 2427,2433 ----
  		case DCH_YYY:
  			if (flag == TO_CHAR)
  			{
! 				snprintf(buff, sizeof(buff), "%03d", YEAR_ABS(tm->tm_year));
  				i = strlen(buff);
  				strcpy(inout, buff + (i - 3));
  				if (S_THth(suf))
***************
*** 2452,2458 ****
  		case DCH_YY:
  			if (flag == TO_CHAR)
  			{
! 				sprintf(buff, "%02d", YEAR_ABS(tm->tm_year));
  				i = strlen(buff);
  				strcpy(inout, buff + (i - 2));
  				if (S_THth(suf))
--- 2457,2463 ----
  		case DCH_YY:
  			if (flag == TO_CHAR)
  			{
! 				snprintf(buff, sizeof(buff), "%02d", YEAR_ABS(tm->tm_year));
  				i = strlen(buff);
  				strcpy(inout, buff + (i - 2));
  				if (S_THth(suf))
***************
*** 2482,2488 ****
  		case DCH_Y:
  			if (flag == TO_CHAR)
  			{
! 				sprintf(buff, "%1d", YEAR_ABS(tm->tm_year));
  				i = strlen(buff);
  				strcpy(inout, buff + (i - 1));
  				if (S_THth(suf))
--- 2487,2493 ----
  		case DCH_Y:
  			if (flag == TO_CHAR)
  			{
! 				snprintf(buff, sizeof(buff), "%1d", YEAR_ABS(tm->tm_year));
  				i = strlen(buff);
  				strcpy(inout, buff + (i - 1));
  				if (S_THth(suf))
***************
*** 2587,2593 ****
  {
  	DCHCacheEntry *ent = NULL;
  
! 	/* counter overload check  - paranoa? */
  	if (DCHCounter + DCH_CACHE_FIELDS >= MAX_INT32)
  	{
  		DCHCounter = 0;
--- 2592,2598 ----
  {
  	DCHCacheEntry *ent = NULL;
  
! 	/* counter overload check  - paranoia? */
  	if (DCHCounter + DCH_CACHE_FIELDS >= MAX_INT32)
  	{
  		DCHCounter = 0;
***************
*** 2615,2621 ****
  #ifdef DEBUG_TO_FROM_CHAR
  		elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
  #endif
! 		strcpy(old->str, str);	/* check str size before this func. */
  		/* old->format fill parser */
  		old->age = (++DCHCounter);
  		return old;
--- 2620,2626 ----
  #ifdef DEBUG_TO_FROM_CHAR
  		elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
  #endif
! 		StrNCpy(old->str, str, DCH_CACHE_SIZE + 1);
  		/* old->format fill parser */
  		old->age = (++DCHCounter);
  		return old;
***************
*** 2627,2633 ****
  		elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);
  #endif
  		ent = DCHCache + n_DCHCache;
! 		strcpy(ent->str, str);	/* check str size before this func. */
  		/* ent->format fill parser */
  		ent->age = (++DCHCounter);
  		++n_DCHCache;
--- 2632,2638 ----
  		elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);
  #endif
  		ent = DCHCache + n_DCHCache;
! 		StrNCpy(ent->str, str, DCH_CACHE_SIZE + 1);
  		/* ent->format fill parser */
  		ent->age = (++DCHCounter);
  		++n_DCHCache;
***************
*** 2643,2649 ****
  	int			i = 0;
  	DCHCacheEntry *ent;
  
! 	/* counter overload check  - paranoa? */
  	if (DCHCounter + DCH_CACHE_FIELDS >= MAX_INT32)
  	{
  		DCHCounter = 0;
--- 2648,2654 ----
  	int			i = 0;
  	DCHCacheEntry *ent;
  
! 	/* counter overload check  - paranoia? */
  	if (DCHCounter + DCH_CACHE_FIELDS >= MAX_INT32)
  	{
  		DCHCounter = 0;
***************
*** 2706,2712 ****
  		parse_format(format, str_fmt, DCH_keywords,
  					 DCH_suff, DCH_index, DCH_TYPE, NULL);
  
! 		(format + len)->type = NODE_TYPE_END;	/* Paranoa? */
  
  	}
  	else
--- 2711,2717 ----
  		parse_format(format, str_fmt, DCH_keywords,
  					 DCH_suff, DCH_index, DCH_TYPE, NULL);
  
! 		(format + len)->type = NODE_TYPE_END;	/* Paranoia? */
  
  	}
  	else
***************
*** 2730,2736 ****
  			parse_format(ent->format, str_fmt, DCH_keywords,
  						 DCH_suff, DCH_index, DCH_TYPE, NULL);
  
! 			(ent->format + len)->type = NODE_TYPE_END;	/* Paranoa? */
  
  #ifdef DEBUG_TO_FROM_CHAR
  			/* dump_node(ent->format, len); */
--- 2735,2741 ----
  			parse_format(ent->format, str_fmt, DCH_keywords,
  						 DCH_suff, DCH_index, DCH_TYPE, NULL);
  
! 			(ent->format + len)->type = NODE_TYPE_END;	/* Paranoia? */
  
  #ifdef DEBUG_TO_FROM_CHAR
  			/* dump_node(ent->format, len); */
***************
*** 2900,2906 ****
  			parse_format(format, str, DCH_keywords,
  						 DCH_suff, DCH_index, DCH_TYPE, NULL);
  
! 			(format + len)->type = NODE_TYPE_END;		/* Paranoa? */
  		}
  		else
  		{
--- 2905,2911 ----
  			parse_format(format, str, DCH_keywords,
  						 DCH_suff, DCH_index, DCH_TYPE, NULL);
  
! 			(format + len)->type = NODE_TYPE_END;		/* Paranoia? */
  		}
  		else
  		{
***************
*** 2923,2929 ****
  				parse_format(ent->format, str, DCH_keywords,
  							 DCH_suff, DCH_index, DCH_TYPE, NULL);
  
! 				(ent->format + len)->type = NODE_TYPE_END;		/* Paranoa? */
  #ifdef DEBUG_TO_FROM_CHAR
  				/* dump_node(ent->format, len); */
  				/* dump_index(DCH_keywords, DCH_index); */
--- 2928,2934 ----
  				parse_format(ent->format, str, DCH_keywords,
  							 DCH_suff, DCH_index, DCH_TYPE, NULL);
  
! 				(ent->format + len)->type = NODE_TYPE_END;		/* Paranoia? */
  #ifdef DEBUG_TO_FROM_CHAR
  				/* dump_node(ent->format, len); */
  				/* dump_index(DCH_keywords, DCH_index); */
***************
*** 3146,3152 ****
  {
  	NUMCacheEntry *ent = NULL;
  
! 	/* counter overload check  - paranoa? */
  	if (NUMCounter + NUM_CACHE_FIELDS >= MAX_INT32)
  	{
  		NUMCounter = 0;
--- 3151,3157 ----
  {
  	NUMCacheEntry *ent = NULL;
  
! 	/* counter overload check  - paranoia? */
  	if (NUMCounter + NUM_CACHE_FIELDS >= MAX_INT32)
  	{
  		NUMCounter = 0;
***************
*** 3183,3189 ****
  #ifdef DEBUG_TO_FROM_CHAR
  		elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
  #endif
! 		strcpy(old->str, str);	/* check str size before this func. */
  		/* old->format fill parser */
  		old->age = (++NUMCounter);
  
--- 3188,3194 ----
  #ifdef DEBUG_TO_FROM_CHAR
  		elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
  #endif
! 		StrNCpy(old->str, str, NUM_CACHE_SIZE + 1);
  		/* old->format fill parser */
  		old->age = (++NUMCounter);
  
***************
*** 3196,3202 ****
  		elog(DEBUG_elog_output, "NEW (%d)", n_NUMCache);
  #endif
  		ent = NUMCache + n_NUMCache;
! 		strcpy(ent->str, str);	/* check str size before this func. */
  		/* ent->format fill parser */
  		ent->age = (++NUMCounter);
  		++n_NUMCache;
--- 3201,3207 ----
  		elog(DEBUG_elog_output, "NEW (%d)", n_NUMCache);
  #endif
  		ent = NUMCache + n_NUMCache;
! 		StrNCpy(ent->str, str, NUM_CACHE_SIZE + 1);
  		/* ent->format fill parser */
  		ent->age = (++NUMCounter);
  		++n_NUMCache;
***************
*** 3214,3220 ****
  	int			i = 0;
  	NUMCacheEntry *ent;
  
! 	/* counter overload check  - paranoa? */
  	if (NUMCounter + NUM_CACHE_FIELDS >= MAX_INT32)
  	{
  		NUMCounter = 0;
--- 3219,3225 ----
  	int			i = 0;
  	NUMCacheEntry *ent;
  
! 	/* counter overload check - paranoia? */
  	if (NUMCounter + NUM_CACHE_FIELDS >= MAX_INT32)
  	{
  		NUMCounter = 0;
***************
*** 3254,3260 ****
   * ----------
   */
  static FormatNode *
! NUM_cache(int len, NUMDesc *Num, char *pars_str, int *flag)
  {
  	FormatNode *format = NULL;
  	char	   *str;
--- 3259,3265 ----
   * ----------
   */
  static FormatNode *
! NUM_cache(int len, NUMDesc *Num, char *pars_str, bool *shouldFree)
  {
  	FormatNode *format = NULL;
  	char	   *str;
***************
*** 3268,3287 ****
  
  	/*
  	 * Allocate new memory if format picture is bigger than static cache
! 	 * and not use cache (call parser always) - flag=1 show this variant
  	 */
  	if (len > NUM_CACHE_SIZE)
  	{
- 
  		format = (FormatNode *) palloc((len + 1) * sizeof(FormatNode));
! 		*flag = 1;
  
  		zeroize_NUM(Num);
  
  		parse_format(format, str, NUM_keywords,
  					 NULL, NUM_index, NUM_TYPE, Num);
  
! 		(format + len)->type = NODE_TYPE_END;	/* Paranoa? */
  
  	}
  	else
--- 3273,3293 ----
  
  	/*
  	 * Allocate new memory if format picture is bigger than static cache
! 	 * and not use cache (call parser always). This branches sets
! 	 * shouldFree to true, accordingly.
  	 */
  	if (len > NUM_CACHE_SIZE)
  	{
  		format = (FormatNode *) palloc((len + 1) * sizeof(FormatNode));
! 
! 		*shouldFree = true;
  
  		zeroize_NUM(Num);
  
  		parse_format(format, str, NUM_keywords,
  					 NULL, NUM_index, NUM_TYPE, Num);
  
! 		(format + len)->type = NODE_TYPE_END;	/* Paranoia? */
  
  	}
  	else
***************
*** 3291,3297 ****
  		 */
  		NUMCacheEntry *ent;
  
! 		flag = 0;
  
  		if ((ent = NUM_cache_search(str)) == NULL)
  		{
--- 3297,3303 ----
  		 */
  		NUMCacheEntry *ent;
  
! 		*shouldFree = false;
  
  		if ((ent = NUM_cache_search(str)) == NULL)
  		{
***************
*** 3305,3311 ****
  			parse_format(ent->format, str, NUM_keywords,
  						 NULL, NUM_index, NUM_TYPE, &ent->Num);
  
! 			(ent->format + len)->type = NODE_TYPE_END;	/* Paranoa? */
  
  		}
  
--- 3311,3317 ----
  			parse_format(ent->format, str, NUM_keywords,
  						 NULL, NUM_index, NUM_TYPE, &ent->Num);
  
! 			(ent->format + len)->type = NODE_TYPE_END;	/* Paranoia? */
  
  		}
  
***************
*** 3782,3802 ****
  				if (Np->last_relevant && Np->number_p > Np->last_relevant &&
  					id != NUM_0)
  					;
- 
  				/*
  				 * terrible Ora format: '0.1' -- 9.9 --> '  .1'
  				 */
  				else if (!IS_ZERO(Np->Num) && *Np->number == '0' &&
  						 Np->number == Np->number_p && Np->Num->post != 0)
  				{
- 
  					if (!IS_FILLMODE(Np->Num))
  					{
  						*Np->inout_p = ' ';
  						++Np->inout_p;
  
  						/*
! 						 * total terible Ora: '0' -- FM9.9 --> '0.'
  						 */
  					}
  					else if (Np->last_relevant && *Np->last_relevant == '.')
--- 3788,3806 ----
  				if (Np->last_relevant && Np->number_p > Np->last_relevant &&
  					id != NUM_0)
  					;
  				/*
  				 * terrible Ora format: '0.1' -- 9.9 --> '  .1'
  				 */
  				else if (!IS_ZERO(Np->Num) && *Np->number == '0' &&
  						 Np->number == Np->number_p && Np->Num->post != 0)
  				{
  					if (!IS_FILLMODE(Np->Num))
  					{
  						*Np->inout_p = ' ';
  						++Np->inout_p;
  
  						/*
! 						 * total terrible Ora: '0' -- FM9.9 --> '0.'
  						 */
  					}
  					else if (Np->last_relevant && *Np->last_relevant == '.')
***************
*** 3804,3815 ****
  						*Np->inout_p = '0';
  						++Np->inout_p;
  					}
- 
  				}
  				else
  				{
  #ifdef DEBUG_TO_FROM_CHAR
! 					elog(DEBUG_elog_output, "Writing digit '%c' to position %d", *Np->number_p, Np->num_curr);
  #endif
  					*Np->inout_p = *Np->number_p;		/* Write DIGIT */
  					++Np->inout_p;
--- 3808,3819 ----
  						*Np->inout_p = '0';
  						++Np->inout_p;
  					}
  				}
  				else
  				{
  #ifdef DEBUG_TO_FROM_CHAR
! 					elog(DEBUG_elog_output, "Writing digit '%c' to position %d",
! 						 *Np->number_p, Np->num_curr);
  #endif
  					*Np->inout_p = *Np->number_p;		/* Write DIGIT */
  					++Np->inout_p;
***************
*** 4260,4266 ****
  	if (len <= 0)							\
  		return DirectFunctionCall1(textin, CStringGetDatum(""));	\
  	result	= (text *) palloc( (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \
! 	format	= NUM_cache(len, &Num, VARDATA(fmt), &flag);		\
  } while (0)
  
  /* ----------
--- 4264,4270 ----
  	if (len <= 0)							\
  		return DirectFunctionCall1(textin, CStringGetDatum(""));	\
  	result	= (text *) palloc( (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \
! 	format	= NUM_cache(len, &Num, VARDATA(fmt), &shouldFree);		\
  } while (0)
  
  /* ----------
***************
*** 4273,4279 ****
  		numstr, plen, sign, TO_CHAR);				\
  	pfree(orgnum);							\
  									\
! 	if (flag)							\
  		pfree(format);						\
  									\
  	/*
--- 4277,4283 ----
  		numstr, plen, sign, TO_CHAR);				\
  	pfree(orgnum);							\
  									\
! 	if (shouldFree)							\
  		pfree(format);						\
  									\
  	/*
***************
*** 4307,4313 ****
  	Datum		result;
  	FormatNode *format;
  	char	   *numstr;
! 	int			flag = 0;
  	int			len = 0;
  	int			scale,
  				precision;
--- 4311,4317 ----
  	Datum		result;
  	FormatNode *format;
  	char	   *numstr;
! 	bool		shouldFree;
  	int			len = 0;
  	int			scale,
  				precision;
***************
*** 4317,4323 ****
  	if (len <= 0)
  		PG_RETURN_NULL();
  
! 	format = NUM_cache(len, &Num, VARDATA(fmt), &flag);
  
  	numstr = (char *) palloc((len * NUM_MAX_ITEM_SIZ) + 1);
  
--- 4321,4327 ----
  	if (len <= 0)
  		PG_RETURN_NULL();
  
! 	format = NUM_cache(len, &Num, VARDATA(fmt), &shouldFree);
  
  	numstr = (char *) palloc((len * NUM_MAX_ITEM_SIZ) + 1);
  
***************
*** 4327,4333 ****
  	scale = Num.post;
  	precision = Max(0, Num.pre) + scale;
  
! 	if (flag)
  		pfree(format);
  
  	result = DirectFunctionCall3(numeric_in,
--- 4331,4337 ----
  	scale = Num.post;
  	precision = Max(0, Num.pre) + scale;
  
! 	if (shouldFree)
  		pfree(format);
  
  	result = DirectFunctionCall3(numeric_in,
***************
*** 4351,4357 ****
  	FormatNode *format;
  	text	   *result,
  			   *result_tmp;
! 	int			flag = 0;
  	int			len = 0,
  				plen = 0,
  				sign = 0;
--- 4355,4361 ----
  	FormatNode *format;
  	text	   *result,
  			   *result_tmp;
! 	bool		shouldFree;
  	int			len = 0,
  				plen = 0,
  				sign = 0;
***************
*** 4451,4457 ****
  	FormatNode *format;
  	text	   *result,
  			   *result_tmp;
! 	int			flag = 0;
  	int			len = 0,
  				plen = 0,
  				sign = 0;
--- 4455,4461 ----
  	FormatNode *format;
  	text	   *result,
  			   *result_tmp;
! 	bool		shouldFree;
  	int			len = 0,
  				plen = 0,
  				sign = 0;
***************
*** 4532,4538 ****
  	FormatNode *format;
  	text	   *result,
  			   *result_tmp;
! 	int			flag = 0;
  	int			len = 0,
  				plen = 0,
  				sign = 0;
--- 4536,4542 ----
  	FormatNode *format;
  	text	   *result,
  			   *result_tmp;
! 	bool		shouldFree;
  	int			len = 0,
  				plen = 0,
  				sign = 0;
***************
*** 4619,4625 ****
  	FormatNode *format;
  	text	   *result,
  			   *result_tmp;
! 	int			flag = 0;
  	int			len = 0,
  				plen = 0,
  				sign = 0;
--- 4623,4629 ----
  	FormatNode *format;
  	text	   *result,
  			   *result_tmp;
! 	bool		shouldFree;
  	int			len = 0,
  				plen = 0,
  				sign = 0;
***************
*** 4647,4653 ****
  		}
  
  		orgnum = (char *) palloc(MAXFLOATWIDTH + 1);
! 		sprintf(orgnum, "%.0f", fabs(val));
  		len = strlen(orgnum);
  		if (Num.pre > len)
  			plen = Num.pre - len;
--- 4651,4657 ----
  		}
  
  		orgnum = (char *) palloc(MAXFLOATWIDTH + 1);
! 		snprintf(orgnum, MAXFLOATWIDTH + 1, "%.0f", fabs(val));
  		len = strlen(orgnum);
  		if (Num.pre > len)
  			plen = Num.pre - len;
***************
*** 4655,4661 ****
  			Num.post = 0;
  		else if (Num.post + len > FLT_DIG)
  			Num.post = FLT_DIG - len;
! 		sprintf(orgnum, "%.*f", Num.post, val);
  
  		if (*orgnum == '-')
  		{						/* < 0 */
--- 4659,4665 ----
  			Num.post = 0;
  		else if (Num.post + len > FLT_DIG)
  			Num.post = FLT_DIG - len;
! 		snprintf(orgnum, MAXFLOATWIDTH + 1, "%.*f", Num.post, val);
  
  		if (*orgnum == '-')
  		{						/* < 0 */
***************
*** 4700,4706 ****
  	FormatNode *format;
  	text	   *result,
  			   *result_tmp;
! 	int			flag = 0;
  	int			len = 0,
  				plen = 0,
  				sign = 0;
--- 4704,4710 ----
  	FormatNode *format;
  	text	   *result,
  			   *result_tmp;
! 	bool		shouldFree;
  	int			len = 0,
  				plen = 0,
  				sign = 0;
***************
*** 4727,4740 ****
  			Num.pre += Num.multi;
  		}
  		orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
! 		len = sprintf(orgnum, "%.0f", fabs(val));
  		if (Num.pre > len)
  			plen = Num.pre - len;
  		if (len >= DBL_DIG)
  			Num.post = 0;
  		else if (Num.post + len > DBL_DIG)
  			Num.post = DBL_DIG - len;
! 		sprintf(orgnum, "%.*f", Num.post, val);
  
  		if (*orgnum == '-')
  		{						/* < 0 */
--- 4731,4744 ----
  			Num.pre += Num.multi;
  		}
  		orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
! 		len = snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.0f", fabs(val));
  		if (Num.pre > len)
  			plen = Num.pre - len;
  		if (len >= DBL_DIG)
  			Num.post = 0;
  		else if (Num.post + len > DBL_DIG)
  			Num.post = DBL_DIG - len;
! 		snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.*f", Num.post, val);
  
  		if (*orgnum == '-')
  		{						/* < 0 */
