From 45a19efa9ec66fa35cc86671e2a1cebfe787fd9f Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 14 Jul 2005 08:42:37 +0000 Subject: [PATCH] Change numericsep to a boolean, and make it locale-aware. --- doc/src/sgml/ref/psql-ref.sgml | 9 +-- src/bin/psql/command.c | 14 ++-- src/bin/psql/print.c | 136 ++++++++++++++++++--------------- src/bin/psql/print.h | 7 +- src/bin/psql/startup.c | 3 +- 5 files changed, 93 insertions(+), 76 deletions(-) diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index 9d76ff207e..d5402bf90d 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -1,5 +1,5 @@ @@ -1496,10 +1496,9 @@ lo_import 152801 numericsep - Specifies the character separator between groups of three digits - to the left of the decimal marker. The default is '' - (none). Setting this to a period also changes the decimal marker - to a comma. + Toggles the display of a locale-aware character to separate groups + of digits to the left of the decimal marker. It also enables + a locale-aware decimal marker. diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 888fa4f55a..0c4db123db 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.148 2005/07/14 06:49:58 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.149 2005/07/14 08:42:37 momjian Exp $ */ #include "postgres_fe.h" #include "command.h" @@ -1420,15 +1420,17 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet) : _("Expanded display is off.\n")); } + /* numeric separators */ else if (strcmp(param, "numericsep") == 0) { - if (value) + popt->topt.numericSep = !popt->topt.numericSep; + if (!quiet) { - free(popt->topt.numericSep); - popt->topt.numericSep = pg_strdup(value); + if (popt->topt.numericSep) + puts(_("Showing numeric separators.")); + else + puts(_("Numeric separators are off.")); } - if (!quiet) - printf(_("Numeric separator is \"%s\".\n"), popt->topt.numericSep); } /* null display */ diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c index 7d4a3a92e5..27e081870a 100644 --- a/src/bin/psql/print.c +++ b/src/bin/psql/print.c @@ -3,7 +3,7 @@ * * 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" @@ -24,11 +24,17 @@ #include #endif +#include + #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) { @@ -47,6 +53,7 @@ static int num_numericseps(const char *my_str) { int old_len, dec_len, int_len; + int groupdigits = atoi(grouping); if (my_str[0] == '-') my_str++; @@ -55,10 +62,10 @@ num_numericseps(const char *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 @@ -68,17 +75,12 @@ len_with_numericsep(const char *my_str) } 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++; @@ -86,9 +88,9 @@ format_numericsep(char *my_str, char *numericsep) 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 */ @@ -99,7 +101,7 @@ format_numericsep(char *my_str, char *numericsep) /* 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); @@ -115,8 +117,9 @@ format_numericsep(char *my_str, char *numericsep) /* 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]; } @@ -135,7 +138,7 @@ print_unaligned_text(const char *title, const char *const *headers, 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; @@ -174,13 +177,12 @@ print_unaligned_text(const char *title, const char *const *headers, 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); } @@ -220,7 +222,7 @@ print_unaligned_vertical(const char *title, const char *const *headers, 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; @@ -251,13 +253,12 @@ print_unaligned_vertical(const char *title, const char *const *headers, 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); } @@ -325,7 +326,7 @@ _print_horizontal_line(const unsigned int col_count, const unsigned int *widths, 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) { @@ -394,8 +395,7 @@ print_aligned_text(const char *title, const char *const *headers, { 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; @@ -480,12 +480,12 @@ print_aligned_text(const char *title, const char *const *headers, /* 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); } @@ -547,7 +547,7 @@ static void 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; @@ -612,8 +612,7 @@ print_aligned_vertical(const char *title, const char *const *headers, { 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; @@ -696,9 +695,8 @@ print_aligned_vertical(const char *title, const char *const *headers, 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 @@ -785,7 +783,7 @@ static void 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; @@ -831,13 +829,12 @@ print_html_text(const char *title, const char *const *headers, /* 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); } @@ -873,7 +870,7 @@ static void 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; @@ -917,13 +914,12 @@ print_html_vertical(const char *title, const char *const *headers, /* 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); } @@ -999,7 +995,7 @@ static void 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; @@ -1060,13 +1056,12 @@ print_latex_text(const char *title, const char *const *headers, /* 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); } @@ -1103,7 +1098,7 @@ static void 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; @@ -1174,13 +1169,12 @@ print_latex_vertical(const char *title, const char *const *headers, 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); } @@ -1221,7 +1215,7 @@ static void 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; @@ -1275,13 +1269,12 @@ print_troff_ms_text(const char *title, const char *const *headers, /* 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); } @@ -1315,7 +1308,7 @@ static void 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; @@ -1345,12 +1338,10 @@ print_troff_ms_vertical(const char *title, const char *const *headers, 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++) { @@ -1390,13 +1381,12 @@ print_troff_ms_vertical(const char *title, const char *const *headers, 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); } @@ -1714,4 +1704,26 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f } -/* 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 */ +} + + diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h index f64f8ba0f8..bb23b7c08c 100644 --- a/src/bin/psql/print.h +++ b/src/bin/psql/print.h @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/print.h,v 1.26 2005/07/10 03:46:13 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/psql/print.h,v 1.27 2005/07/14 08:42:37 momjian Exp $ */ #ifndef PRINT_H #define PRINT_H @@ -40,7 +40,8 @@ typedef struct _printTableOpt char *fieldSep; /* field separator for unaligned text mode */ char *recordSep; /* record separator for unaligned text * mode */ - char *numericSep; /* numeric units separator */ + bool numericSep; /* locale-aware numeric units separator and + * decimal marker */ char *tableAttr; /* attributes for HTML */ int encoding; /* character encoding */ bool normal_query; /* are we presenting the results of a @@ -86,6 +87,8 @@ typedef struct _printQueryOpt void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *flog); +void setDecimalLocale(void); + #ifndef __CYGWIN__ #define DEFAULT_PAGER "more" #else diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index 9caecbe449..3f603757c4 100644 --- a/src/bin/psql/startup.c +++ b/src/bin/psql/startup.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.118 2005/06/21 04:02:33 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.119 2005/07/14 08:42:37 momjian Exp $ */ #include "postgres_fe.h" @@ -130,6 +130,7 @@ main(int argc, char *argv[]) setvbuf(stderr, NULL, _IONBF, 0); setup_win32_locks(); #endif + setDecimalLocale(); pset.cur_cmd_source = stdin; pset.cur_cmd_interactive = false; pset.encoding = PQenv2encoding(); -- GitLab