*
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.66 2005/07/14 07:32:01 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.67 2005/07/14 08:42:37 momjian Exp $
*/
#include "postgres_fe.h"
#include "common.h"
#include <termios.h>
#endif
+#include <locale.h>
+
#include "pqsignal.h"
#include "libpq-fe.h"
#include "mbprint.h"
+static char *decimal_point;
+static char *grouping;
+static char *thousands_sep;
+
static void *
pg_local_malloc(size_t size)
{
num_numericseps(const char *my_str)
{
int old_len, dec_len, int_len;
+ int groupdigits = atoi(grouping);
if (my_str[0] == '-')
my_str++;
dec_len = strchr(my_str, '.') ? strlen(strchr(my_str, '.')) : 0;
int_len = old_len - dec_len;
- if (int_len % 3 != 0)
- return int_len / 3;
+ if (int_len % groupdigits != 0)
+ return int_len / groupdigits;
else
- return int_len / 3 - 1; /* no leading separator */
+ return int_len / groupdigits - 1; /* no leading separator */
}
static int
}
static void
-format_numericsep(char *my_str, char *numericsep)
+format_numericsep(char *my_str)
{
int i, j, digits_before_sep, old_len, new_len, dec_len, int_len;
- char *dec_point;
char *new_str;
char *dec_value;
-
- if (strcmp(numericsep, ".") != 0)
- dec_point = ".";
- else
- dec_point = ",";
+ int groupdigits = atoi(grouping);
if (my_str[0] == '-')
my_str++;
old_len = strlen(my_str);
dec_len = strchr(my_str, '.') ? strlen(strchr(my_str, '.')) : 0;
int_len = old_len - dec_len;
- digits_before_sep = int_len % 3;
+ digits_before_sep = int_len % groupdigits;
- new_len = int_len + int_len / 3 + dec_len;
+ new_len = int_len + int_len / groupdigits + dec_len;
if (digits_before_sep == 0)
new_len--; /* no leading separator */
/* hit decimal point */
if (my_str[i] == '.')
{
- new_str[j] = *dec_point;
+ new_str[j] = *decimal_point;
new_str[j+1] = '\0';
dec_value = strchr(my_str, '.');
strcat(new_str, ++dec_value);
/* add separator? */
if (i != 0 &&
- (i - (digits_before_sep ? digits_before_sep : 3)) % 3 == 0)
- new_str[j++] = *numericsep;
+ (i - (digits_before_sep ? digits_before_sep : groupdigits))
+ % groupdigits == 0)
+ new_str[j++] = *thousands_sep;
new_str[j] = my_str[i];
}
const char *const *cells, const char *const *footers,
const char *opt_align, const char *opt_fieldsep,
const char *opt_recordsep, bool opt_tuples_only,
- char *opt_numericsep, FILE *fout)
+ bool opt_numericsep, FILE *fout)
{
unsigned int col_count = 0;
unsigned int i;
fputs(opt_recordsep, fout);
need_recordsep = false;
}
- if ((opt_align[i % col_count] == 'r') && strlen(*ptr) > 0 &&
- opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ if (opt_align[i % col_count] == 'r' && opt_numericsep)
{
char *my_cell = pg_local_malloc(len_with_numericsep(*ptr) + 1);
strcpy(my_cell, *ptr);
- format_numericsep(my_cell, opt_numericsep);
+ format_numericsep(my_cell);
fputs(my_cell, fout);
free(my_cell);
}
const char *const *cells,
const char *const *footers, const char *opt_align,
const char *opt_fieldsep, const char *opt_recordsep,
- bool opt_tuples_only, char *opt_numericsep, FILE *fout)
+ bool opt_tuples_only, bool opt_numericsep, FILE *fout)
{
unsigned int col_count = 0;
unsigned int i;
fputs(headers[i % col_count], fout);
fputs(opt_fieldsep, fout);
- if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
- opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ if (opt_align[i % col_count] == 'r' && opt_numericsep)
{
char *my_cell = pg_local_malloc(len_with_numericsep(*ptr) + 1);
strcpy(my_cell, *ptr);
- format_numericsep(my_cell, opt_numericsep);
+ format_numericsep(my_cell);
fputs(my_cell, fout);
free(my_cell);
}
static void
print_aligned_text(const char *title, const char *const *headers,
const char *const *cells, const char *const *footers,
- const char *opt_align, bool opt_tuples_only, char *opt_numericsep,
+ const char *opt_align, bool opt_tuples_only, bool opt_numericsep,
unsigned short int opt_border, int encoding,
FILE *fout)
{
{
int numericseps;
- if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
- opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ if (opt_align[i % col_count] == 'r' && opt_numericsep)
numericseps = num_numericseps(*ptr);
else
numericseps = 0;
/* content */
if (opt_align[i % col_count] == 'r')
{
- if (strlen(*ptr) > 0 && opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ if (opt_numericsep)
{
char *my_cell = pg_local_malloc(cell_w[i] + 1);
strcpy(my_cell, *ptr);
- format_numericsep(my_cell, opt_numericsep);
+ format_numericsep(my_cell);
fprintf(fout, "%*s%s", widths[i % col_count] - cell_w[i], "", my_cell);
free(my_cell);
}
print_aligned_vertical(const char *title, const char *const *headers,
const char *const *cells, const char *const *footers,
const char *opt_align, bool opt_tuples_only,
- char *opt_numericsep, unsigned short int opt_border,
+ bool opt_numericsep, unsigned short int opt_border,
int encoding, FILE *fout)
{
unsigned int col_count = 0;
{
int numericseps;
- if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
- opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ if (opt_align[i % col_count] == 'r' && opt_numericsep)
numericseps = num_numericseps(*ptr);
else
numericseps = 0;
char *my_cell = pg_local_malloc(cell_w[i] + 1);
strcpy(my_cell, *ptr);
- if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
- opt_numericsep != NULL && strlen(opt_numericsep) > 0)
- format_numericsep(my_cell, opt_numericsep);
+ if (opt_align[i % col_count] == 'r' && opt_numericsep)
+ format_numericsep(my_cell);
if (opt_border < 2)
puts(my_cell);
else
print_html_text(const char *title, const char *const *headers,
const char *const *cells, const char *const *footers,
const char *opt_align, bool opt_tuples_only,
- char *opt_numericsep, unsigned short int opt_border,
+ bool opt_numericsep, unsigned short int opt_border,
const char *opt_table_attr, FILE *fout)
{
unsigned int col_count = 0;
/* is string only whitespace? */
if ((*ptr)[strspn(*ptr, " \t")] == '\0')
fputs(" ", fout);
- else if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
- opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ else if (opt_align[i % col_count] == 'r' && opt_numericsep)
{
char *my_cell = pg_local_malloc(len_with_numericsep(*ptr) + 1);
strcpy(my_cell, *ptr);
- format_numericsep(my_cell, opt_numericsep);
+ format_numericsep(my_cell);
html_escaped_print(my_cell, fout);
free(my_cell);
}
print_html_vertical(const char *title, const char *const *headers,
const char *const *cells, const char *const *footers,
const char *opt_align, bool opt_tuples_only,
- char *opt_numericsep, unsigned short int opt_border,
+ bool opt_numericsep, unsigned short int opt_border,
const char *opt_table_attr, FILE *fout)
{
unsigned int col_count = 0;
/* is string only whitespace? */
if ((*ptr)[strspn(*ptr, " \t")] == '\0')
fputs(" ", fout);
- else if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
- opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ else if (opt_align[i % col_count] == 'r' && opt_numericsep)
{
char *my_cell = pg_local_malloc(len_with_numericsep(*ptr) + 1);
strcpy(my_cell, *ptr);
- format_numericsep(my_cell, opt_numericsep);
+ format_numericsep(my_cell);
html_escaped_print(my_cell, fout);
free(my_cell);
}
print_latex_text(const char *title, const char *const *headers,
const char *const *cells, const char *const *footers,
const char *opt_align, bool opt_tuples_only,
- char *opt_numericsep, unsigned short int opt_border,
+ bool opt_numericsep, unsigned short int opt_border,
FILE *fout)
{
unsigned int col_count = 0;
/* print cells */
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
- if (strlen(*ptr) != 0 &&
- opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ if (opt_numericsep)
{
char *my_cell = pg_local_malloc(len_with_numericsep(*ptr) + 1);
strcpy(my_cell, *ptr);
- format_numericsep(my_cell, opt_numericsep);
+ format_numericsep(my_cell);
latex_escaped_print(my_cell, fout);
free(my_cell);
}
print_latex_vertical(const char *title, const char *const *headers,
const char *const *cells, const char *const *footers,
const char *opt_align, bool opt_tuples_only,
- char *opt_numericsep, unsigned short int opt_border,
+ bool opt_numericsep, unsigned short int opt_border,
FILE *fout)
{
unsigned int col_count = 0;
if (footers && !opt_tuples_only)
for (ptr = footers; *ptr; ptr++)
{
- if (strlen(*ptr) != 0 &&
- opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ if (opt_numericsep)
{
char *my_cell = pg_local_malloc(len_with_numericsep(*ptr) + 1);
strcpy(my_cell, *ptr);
- format_numericsep(my_cell, opt_numericsep);
+ format_numericsep(my_cell);
latex_escaped_print(my_cell, fout);
free(my_cell);
}
print_troff_ms_text(const char *title, const char *const *headers,
const char *const *cells, const char *const *footers,
const char *opt_align, bool opt_tuples_only,
- char *opt_numericsep, unsigned short int opt_border,
+ bool opt_numericsep, unsigned short int opt_border,
FILE *fout)
{
unsigned int col_count = 0;
/* print cells */
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
- if (strlen(*ptr) != 0 &&
- opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ if (opt_numericsep)
{
char *my_cell = pg_local_malloc(len_with_numericsep(*ptr) + 1);
strcpy(my_cell, *ptr);
- format_numericsep(my_cell, opt_numericsep);
+ format_numericsep(my_cell);
troff_ms_escaped_print(my_cell, fout);
free(my_cell);
}
print_troff_ms_vertical(const char *title, const char *const *headers,
const char *const *cells, const char *const *footers,
const char *opt_align, bool opt_tuples_only,
- char *opt_numericsep, unsigned short int opt_border,
+ bool opt_numericsep, unsigned short int opt_border,
FILE *fout)
{
unsigned int col_count = 0;
if (opt_tuples_only)
fputs("c l;\n", fout);
-
/* count columns */
for (ptr = headers; *ptr; ptr++)
col_count++;
-
/* print records */
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
troff_ms_escaped_print(headers[i % col_count], fout);
fputc('\t', fout);
- if (strlen(*ptr) != 0 &&
- opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ if (opt_numericsep)
{
char *my_cell = pg_local_malloc(len_with_numericsep(*ptr) + 1);
strcpy(my_cell, *ptr);
- format_numericsep(my_cell, opt_numericsep);
+ format_numericsep(my_cell);
troff_ms_escaped_print(my_cell, fout);
free(my_cell);
}
}
-/* the end */
+void
+setDecimalLocale(void)
+{
+ struct lconv *extlconv;
+
+ extlconv = localeconv();
+
+ /* These are treated as single-byte strings in the code */
+ if (*extlconv->decimal_point)
+ decimal_point = strdup(extlconv->decimal_point);
+ else
+ decimal_point = "."; /* SQL output standard */
+ if (*extlconv->grouping && atoi(extlconv->grouping) > 0)
+ grouping = strdup(extlconv->grouping);
+ else
+ grouping = "3"; /* most common */
+ if (*extlconv->thousands_sep)
+ thousands_sep = strdup(extlconv->thousands_sep);
+ else
+ thousands_sep = ","; /* matches SQL standard decimal marker */
+}
+
+