diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index cab9e6e..f7343d1 100644
*** a/src/bin/psql/print.c
--- b/src/bin/psql/print.c
***************
*** 39,46 ****
   */
  volatile bool cancel_pressed = false;
  
  static char *decimal_point;
! static char *grouping;
  static char *thousands_sep;
  
  static char default_footer[100];
--- 39,47 ----
   */
  volatile bool cancel_pressed = false;
  
+ /* info for locale-aware numeric formatting; set up by setDecimalLocale() */
  static char *decimal_point;
! static int	groupdigits;
  static char *thousands_sep;
  
  static char default_footer[100];
*************** static void IsPagerNeeded(const printTab
*** 196,239 ****
  static void print_aligned_vertical(const printTableContent *cont, FILE *fout);
  
  
  static int
  integer_digits(const char *my_str)
  {
! 	int			frac_len;
! 
! 	if (my_str[0] == '-')
  		my_str++;
! 
! 	frac_len = strchr(my_str, '.') ? strlen(strchr(my_str, '.')) : 0;
! 
! 	return strlen(my_str) - frac_len;
  }
  
! /* Return additional length required for locale-aware numeric output */
  static int
  additional_numeric_locale_len(const char *my_str)
  {
  	int			int_len = integer_digits(my_str),
  				len = 0;
- 	int			groupdigits = atoi(grouping);
  
! 	if (int_len > 0)
! 		/* Don't count a leading separator */
! 		len = (int_len / groupdigits - (int_len % groupdigits == 0)) *
! 			strlen(thousands_sep);
  
  	if (strchr(my_str, '.') != NULL)
! 		len += strlen(decimal_point) - strlen(".");
  
  	return len;
  }
  
- static int
- strlen_with_numeric_locale(const char *my_str)
- {
- 	return strlen(my_str) + additional_numeric_locale_len(my_str);
- }
- 
  /*
   * Returns the appropriately formatted string in a new allocated block,
   * caller must free
--- 197,231 ----
  static void print_aligned_vertical(const printTableContent *cont, FILE *fout);
  
  
+ /* Count number of digits in integral part of number */
  static int
  integer_digits(const char *my_str)
  {
! 	/* ignoring any sign ... */
! 	if (my_str[0] == '-' || my_str[0] == '+')
  		my_str++;
! 	/* ... count initial integral digits */
! 	return strspn(my_str, "0123456789");
  }
  
! /* Compute additional length required for locale-aware numeric output */
  static int
  additional_numeric_locale_len(const char *my_str)
  {
  	int			int_len = integer_digits(my_str),
  				len = 0;
  
! 	/* Account for added thousands_sep instances */
! 	if (int_len > groupdigits)
! 		len += ((int_len - 1) / groupdigits) * strlen(thousands_sep);
  
+ 	/* Account for possible additional length of decimal_point */
  	if (strchr(my_str, '.') != NULL)
! 		len += strlen(decimal_point) - 1;
  
  	return len;
  }
  
  /*
   * Returns the appropriately formatted string in a new allocated block,
   * caller must free
*************** strlen_with_numeric_locale(const char *m
*** 241,293 ****
  static char *
  format_numeric_locale(const char *my_str)
  {
  	int			i,
- 				j,
- 				int_len = integer_digits(my_str),
  				leading_digits;
! 	int			groupdigits = atoi(grouping);
! 	int			new_str_start = 0;
! 	char	   *new_str = pg_malloc(strlen_with_numeric_locale(my_str) + 1);
  
! 	leading_digits = (int_len % groupdigits != 0) ?
! 		int_len % groupdigits : groupdigits;
  
! 	if (my_str[0] == '-')		/* skip over sign, affects grouping
! 								 * calculations */
  	{
! 		new_str[0] = my_str[0];
  		my_str++;
- 		new_str_start = 1;
  	}
  
! 	for (i = 0, j = new_str_start;; i++, j++)
  	{
! 		/* Hit decimal point? */
! 		if (my_str[i] == '.')
  		{
! 			strcpy(&new_str[j], decimal_point);
! 			j += strlen(decimal_point);
! 			/* add fractional part */
! 			strcpy(&new_str[j], &my_str[i] + 1);
! 			break;
  		}
  
! 		/* End of string? */
! 		if (my_str[i] == '\0')
! 		{
! 			new_str[j] = '\0';
! 			break;
! 		}
  
! 		/* Add separator? */
! 		if (i != 0 && (i - leading_digits) % groupdigits == 0)
! 		{
! 			strcpy(&new_str[j], thousands_sep);
! 			j += strlen(thousands_sep);
! 		}
  
! 		new_str[j] = my_str[i];
! 	}
  
  	return new_str;
  }
--- 233,283 ----
  static char *
  format_numeric_locale(const char *my_str)
  {
+ 	int			new_len = strlen(my_str) + additional_numeric_locale_len(my_str);
+ 	char	   *new_str = pg_malloc(new_len + 1);
+ 	int			int_len = integer_digits(my_str);
  	int			i,
  				leading_digits;
! 	int			new_str_pos = 0;
  
! 	/* number of digits in first thousands group */
! 	leading_digits = int_len % groupdigits;
! 	if (leading_digits == 0)
! 		leading_digits = groupdigits;
  
! 	/* process sign */
! 	if (my_str[0] == '-' || my_str[0] == '+')
  	{
! 		new_str[new_str_pos++] = my_str[0];
  		my_str++;
  	}
  
! 	/* process integer part of number */
! 	for (i = 0; i < int_len; i++)
  	{
! 		/* Time to insert separator? */
! 		if (i > 0 && --leading_digits == 0)
  		{
! 			strcpy(&new_str[new_str_pos], thousands_sep);
! 			new_str_pos += strlen(thousands_sep);
! 			leading_digits = groupdigits;
  		}
+ 		new_str[new_str_pos++] = my_str[i];
+ 	}
  
! 	/* handle decimal point if any */
! 	if (my_str[i] == '.')
! 	{
! 		strcpy(&new_str[new_str_pos], decimal_point);
! 		new_str_pos += strlen(decimal_point);
! 		i++;
! 	}
  
! 	/* copy the rest (fractional digits and/or exponent, and \0 terminator) */
! 	strcpy(&new_str[new_str_pos], &my_str[i]);
  
! 	/* assert we didn't underestimate new_len (an overestimate is OK) */
! 	assert(strlen(new_str) <= new_len);
  
  	return new_str;
  }
*************** setDecimalLocale(void)
*** 3241,3250 ****
  		decimal_point = pg_strdup(extlconv->decimal_point);
  	else
  		decimal_point = ".";	/* SQL output standard */
  	if (*extlconv->grouping && atoi(extlconv->grouping) > 0)
! 		grouping = pg_strdup(extlconv->grouping);
  	else
! 		grouping = "3";			/* most common */
  
  	/* similar code exists in formatting.c */
  	if (*extlconv->thousands_sep)
--- 3231,3241 ----
  		decimal_point = pg_strdup(extlconv->decimal_point);
  	else
  		decimal_point = ".";	/* SQL output standard */
+ 
  	if (*extlconv->grouping && atoi(extlconv->grouping) > 0)
! 		groupdigits = atoi(extlconv->grouping);
  	else
! 		groupdigits = 3;		/* most common */
  
  	/* similar code exists in formatting.c */
  	if (*extlconv->thousands_sep)
