From: John Darrington Date: Sat, 18 Jul 2009 11:20:38 +0000 (+0200) Subject: Merge commit 'origin/data-encoding' X-Git-Tag: build37~53 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp-builds.git;a=commitdiff_plain;h=8f04b0ced35a66cfdebefbcb53c81979add36ca3;hp=-c Merge commit 'origin/data-encoding' Conflicts: src/language/dictionary/split-file.c --- 8f04b0ced35a66cfdebefbcb53c81979add36ca3 diff --combined src/data/sys-file-reader.c index cbbbdd15,0f583a12..9978d43a --- a/src/data/sys-file-reader.c +++ b/src/data/sys-file-reader.c @@@ -25,6 -25,7 +25,7 @@@ #include #include + #include #include #include #include @@@ -186,6 -187,62 +187,62 @@@ static void read_long_string_value_labe size_t size, size_t count, struct dictionary *); + /* Convert all the strings in DICT from the dict encoding to UTF8 */ + static void + recode_strings (struct dictionary *dict) + { + int i; + + const char *enc = dict_get_encoding (dict); + + if ( NULL == enc) + enc = get_default_encoding (); + + for (i = 0 ; i < dict_get_var_cnt (dict); ++i) + { + /* Convert the long variable name */ + struct variable *var = dict_get_var (dict, i); + const char *native_name = var_get_name (var); + char *utf8_name = recode_string (UTF8, enc, native_name, -1); + if ( 0 != strcmp (utf8_name, native_name)) + { + if ( NULL == dict_lookup_var (dict, utf8_name)) + dict_rename_var (dict, var, utf8_name); + else + msg (MW, + _("Recoded variable name duplicates an existing `%s' within system file."), utf8_name); + } + + free (utf8_name); + + /* Convert the variable label */ + if (var_has_label (var)) + { + char *utf8_label = recode_string (UTF8, enc, var_get_label (var), -1); + var_set_label (var, utf8_label); + free (utf8_label); + } + + if (var_has_value_labels (var)) + { + const struct val_lab *vl = NULL; + const struct val_labs *vlabs = var_get_value_labels (var); + + for (vl = val_labs_first (vlabs); vl != NULL; vl = val_labs_next (vlabs, vl)) + { + const union value *val = val_lab_get_value (vl); + const char *label = val_lab_get_label (vl); + char *new_label = NULL; + + new_label = recode_string (UTF8, enc, label, -1); + + var_replace_value_label (var, val, new_label); + free (new_label); + } + } + } + } + /* Opens the system file designated by file handle FH for reading. Reads the system file's dictionary into *DICT. If INFO is non-null, then it receives additional info about the @@@ -303,6 -360,8 +360,8 @@@ sfm_open_reader (struct file_handle *fh r->has_long_var_names = true; } + recode_strings (*dict); + /* Read record 999 data, which is just filler. */ read_int (r); @@@ -518,7 -577,7 +577,7 @@@ read_variable_record (struct sfm_reade /* Create variable. */ if (width < 0 || width > 255) - sys_error (r, _("Bad variable width %d."), width); + sys_error (r, _("Bad width %d for variable %s."), width, name); var = dict_create_var (dict, name, width); if (var == NULL) sys_error (r, @@@ -582,7 -641,7 +641,7 @@@ value_set_missing (&value, mv_width); for (i = 0; i < missing_value_code; i++) { - char *s = value_str_rw (&value, mv_width); + uint8_t *s = value_str_rw (&value, mv_width); read_bytes (r, s, 8); mv_add_str (&mv, s); } @@@ -922,16 -981,11 +981,16 @@@ read_machine_float_info (struct sfm_rea size, count); if (sysmis != SYSMIS) - sys_warn (r, _("File specifies unexpected value %g as SYSMIS."), sysmis); + sys_warn (r, _("File specifies unexpected value %g as %s."), + sysmis, "SYSMIS"); + if (highest != HIGHEST) - sys_warn (r, _("File specifies unexpected value %g as HIGHEST."), highest); + sys_warn (r, _("File specifies unexpected value %g as %s."), + highest, "HIGHEST"); + if (lowest != LOWEST) - sys_warn (r, _("File specifies unexpected value %g as LOWEST."), lowest); + sys_warn (r, _("File specifies unexpected value %g as %s."), + lowest, "LOWEST"); } /* Read record type 7, subtype 11, which specifies how variables @@@ -1138,7 -1192,7 +1197,7 @@@ read_value_labels (struct sfm_reader *r struct label { - char raw_value[8]; /* Value as uninterpreted bytes. */ + uint8_t raw_value[8]; /* Value as uninterpreted bytes. */ union value value; /* Value. */ char *label; /* Null-terminated label string. */ }; @@@ -1236,7 -1290,7 +1295,7 @@@ value_init_pool (subpool, &label->value, max_width); if (var_is_alpha (var[0])) - buf_copy_rpad (value_str_rw (&label->value, max_width), max_width, + u8_buf_copy_rpad (value_str_rw (&label->value, max_width), max_width, label->raw_value, sizeof label->raw_value, ' '); else label->value.f = float_get_double (r->float_format, label->raw_value); @@@ -1416,7 -1470,7 +1475,7 @@@ read_long_string_value_labels (struct s /* Read value. */ value_length = read_int (r); if (value_length == width) - read_string (r, value_str_rw (&value, width), width + 1); + read_bytes (r, value_str_rw (&value, width), width); else { sys_warn (r, _("Ignoring long string value %zu for variable %s, " @@@ -1473,11 -1527,11 +1532,11 @@@ static void partial_record (struct sfm_ static void read_error (struct casereader *, const struct sfm_reader *); static bool read_case_number (struct sfm_reader *, double *); - static bool read_case_string (struct sfm_reader *, char *, size_t); + static bool read_case_string (struct sfm_reader *, uint8_t *, size_t); static int read_opcode (struct sfm_reader *); static bool read_compressed_number (struct sfm_reader *, double *); - static bool read_compressed_string (struct sfm_reader *, char *); - static bool read_whole_strings (struct sfm_reader *, char *, size_t); + static bool read_compressed_string (struct sfm_reader *, uint8_t *); + static bool read_whole_strings (struct sfm_reader *, uint8_t *, size_t); static bool skip_whole_strings (struct sfm_reader *, size_t); /* Reads and returns one case from READER's file. Returns a null @@@ -1512,7 -1566,7 +1571,7 @@@ sys_file_casereader_read (struct casere } else { - char *s = value_str_rw (v, sv->var_width); + uint8_t *s = value_str_rw (v, sv->var_width); if (!read_case_string (r, s + sv->offset, sv->segment_width)) goto eof; if (!skip_whole_strings (r, ROUND_DOWN (sv->padding, 8))) @@@ -1574,7 -1628,7 +1633,7 @@@ read_case_number (struct sfm_reader *r Returns true if successful, false if end of file is reached immediately. */ static bool - read_case_string (struct sfm_reader *r, char *s, size_t length) + read_case_string (struct sfm_reader *r, uint8_t *s, size_t length) { size_t whole = ROUND_DOWN (length, 8); size_t partial = length % 8; @@@ -1587,7 -1641,7 +1646,7 @@@ if (partial) { - char bounce[8]; + uint8_t bounce[8]; if (!read_whole_strings (r, bounce, sizeof bounce)) { if (whole) @@@ -1658,7 -1712,7 +1717,7 @@@ read_compressed_number (struct sfm_read Returns true if successful, false if end of file is reached immediately. */ static bool - read_compressed_string (struct sfm_reader *r, char *dst) + read_compressed_string (struct sfm_reader *r, uint8_t *dst) { switch (read_opcode (r)) { @@@ -1687,7 -1741,7 +1746,7 @@@ Returns true if successful, false if end of file is reached immediately. */ static bool - read_whole_strings (struct sfm_reader *r, char *s, size_t length) + read_whole_strings (struct sfm_reader *r, uint8_t *s, size_t length) { assert (length % 8 == 0); if (!r->compressed) @@@ -1715,7 -1769,7 +1774,7 @@@ static bool skip_whole_strings (struct sfm_reader *r, size_t length) { - char buffer[1024]; + uint8_t buffer[1024]; assert (length < sizeof buffer); return read_whole_strings (r, buffer, length); } diff --combined src/data/value.h index 6955eea0,84f08d87..f9782e2d --- a/src/data/value.h +++ b/src/data/value.h @@@ -20,6 -20,7 +20,7 @@@ #include #include #include + #include #include #include "xalloc.h" @@@ -45,8 -46,8 +46,8 @@@ union value { double f; - char short_string[MAX_SHORT_STRING]; - char *long_string; + uint8_t short_string[MAX_SHORT_STRING]; + uint8_t *long_string; }; static inline void value_init (union value *, int width); @@@ -55,17 -56,20 +56,17 @@@ static inline bool value_try_init (unio static inline void value_destroy (union value *, int width); static inline double value_num (const union value *); - static inline const char *value_str (const union value *, int width); - static inline char *value_str_rw (union value *, int width); + static inline const uint8_t *value_str (const union value *, int width); + static inline uint8_t *value_str_rw (union value *, int width); -int compare_values (const void *, const void *, const void *var); -unsigned hash_value (const void *, const void *var); - static inline void value_copy (union value *, const union value *, int width); void value_copy_rpad (union value *, int dst_width, const union value *, int src_width, char pad); - void value_copy_str_rpad (union value *, int dst_width, const char *, + void value_copy_str_rpad (union value *, int dst_width, const uint8_t *, char pad); void value_copy_buf_rpad (union value *dst, int dst_width, - const char *src, size_t src_len, char pad); + const uint8_t *src, size_t src_len, char pad); void value_set_missing (union value *, int width); int value_compare_3way (const union value *, const union value *, int width); bool value_equal (const union value *, const union value *, int width); @@@ -147,7 -151,7 +148,7 @@@ value_num (const union value *v It is important that WIDTH be the actual value that was passed to value_init. Passing, e.g., a smaller value because only that number of bytes will be accessed will not always work. */ - static inline const char * + static inline const uint8_t * value_str (const union value *v, int width) { assert (width > 0); @@@ -161,7 -165,7 +162,7 @@@ It is important that WIDTH be the actual value that was passed to value_init. Passing, e.g., a smaller value because only that number of bytes will be accessed will not always work. */ - static inline char * + static inline uint8_t * value_str_rw (union value *v, int width) { assert (width > 0); diff --combined src/language/data-io/data-parser.c index e7e92bf6,8f189b1b..6ec3d0d5 --- a/src/language/data-io/data-parser.c +++ b/src/language/data-io/data-parser.c @@@ -41,6 -41,7 +41,7 @@@ /* Data parser for textual data like that read by DATA LIST. */ struct data_parser { + const struct dictionary *dict; /*Dictionary of destination */ enum data_parser_type type; /* Type of data to parse. */ int skip_records; /* Records to skip before first real data. */ casenumber max_cases; /* Max number of cases to read. */ @@@ -79,7 -80,7 +80,7 @@@ static void set_any_sep (struct data_pa /* Creates and returns a new data parser. */ struct data_parser * - data_parser_create (void) + data_parser_create (const struct dictionary *dict) { struct data_parser *parser = xmalloc (sizeof *parser); @@@ -91,6 -92,7 +92,7 @@@ parser->fields = NULL; parser->field_cnt = 0; parser->field_allocated = 0; + parser->dict = dict; parser->span = true; parser->empty_line_has_field = false; @@@ -505,7 -507,7 +507,7 @@@ static boo parse_fixed (const struct data_parser *parser, struct dfm_reader *reader, struct ccase *c) { - enum legacy_encoding encoding = dfm_reader_get_legacy_encoding (reader); + const char *encoding = dfm_reader_get_legacy_encoding (reader); struct field *f; int row; @@@ -531,6 -533,7 +533,7 @@@ f->format.w), encoding, f->format.type, f->format.d, f->first_column, f->first_column + f->format.w, + parser->dict, case_data_rw_idx (c, f->case_idx), fmt_var_width (&f->format)); @@@ -547,7 -550,7 +550,7 @@@ static boo parse_delimited_span (const struct data_parser *parser, struct dfm_reader *reader, struct ccase *c) { - enum legacy_encoding encoding = dfm_reader_get_legacy_encoding (reader); + const char *encoding = dfm_reader_get_legacy_encoding (reader); struct string tmp = DS_EMPTY_INITIALIZER; struct field *f; @@@ -574,6 -577,7 +577,7 @@@ data_in (s, encoding, f->format.type, 0, first_column, last_column, + parser->dict, case_data_rw_idx (c, f->case_idx), fmt_var_width (&f->format)); } @@@ -588,7 -592,7 +592,7 @@@ static boo parse_delimited_no_span (const struct data_parser *parser, struct dfm_reader *reader, struct ccase *c) { - enum legacy_encoding encoding = dfm_reader_get_legacy_encoding (reader); + const char *encoding = dfm_reader_get_legacy_encoding (reader); struct string tmp = DS_EMPTY_INITIALIZER; struct substring s; struct field *f; @@@ -614,6 -618,7 +618,7 @@@ data_in (s, encoding, f->format.type, 0, first_column, last_column, + parser->dict, case_data_rw_idx (c, f->case_idx), fmt_var_width (&f->format)); } @@@ -656,9 -661,9 +661,9 @@@ dump_fixed_table (const struct data_par int row = i + 1; tab_text (t, 0, row, TAB_LEFT, f->name); - tab_text (t, 1, row, TAT_PRINTF, "%d", f->record); - tab_text (t, 2, row, TAT_PRINTF, "%3d-%3d", - f->first_column, f->first_column + f->format.w - 1); + tab_text_format (t, 1, row, 0, "%d", f->record); + tab_text_format (t, 2, row, 0, "%3d-%3d", + f->first_column, f->first_column + f->format.w - 1); tab_text (t, 3, row, TAB_LEFT | TAB_FIX, fmt_to_string (&f->format, fmt_string)); } diff --combined src/language/data-io/print.c index 34042aa8,c981bb1d..e345477b --- a/src/language/data-io/print.c +++ b/src/language/data-io/print.c @@@ -32,6 -32,7 +32,7 @@@ #include #include #include + #include #include #include #include @@@ -83,7 -84,7 +84,7 @@@ struct print_trn struct pool *pool; /* Stores related data. */ bool eject; /* Eject page before printing? */ bool include_prefix; /* Prefix lines with space? */ - enum legacy_encoding encoding; /* Encoding to use for output. */ + const char *encoding; /* Encoding to use for output. */ struct dfm_writer *writer; /* Output file, NULL=listing file. */ struct ll_list specs; /* List of struct prt_out_specs. */ size_t record_cnt; /* Number of records to write. */ @@@ -413,9 -414,8 +414,9 @@@ dump_table (struct print_trns *trns, co switch (spec->type) { case PRT_LITERAL: - tab_text (t, 0, row, TAB_LEFT | TAB_FIX | TAT_PRINTF, "\"%.*s\"", - (int) ds_length (&spec->string), ds_data (&spec->string)); + tab_text_format (t, 0, row, TAB_LEFT | TAB_FIX, "\"%.*s\"", + (int) ds_length (&spec->string), + ds_data (&spec->string)); width = ds_length (&spec->string); break; case PRT_VAR: @@@ -427,9 -427,9 +428,9 @@@ default: NOT_REACHED (); } - tab_text (t, 1, row, TAT_PRINTF, "%d", spec->record); - tab_text (t, 2, row, TAT_PRINTF, "%3d-%3d", - spec->first_column, spec->first_column + width - 1); + tab_text_format (t, 1, row, 0, "%d", spec->record); + tab_text_format (t, 2, row, 0, "%3d-%3d", + spec->first_column, spec->first_column + width - 1); row++; } @@@ -480,12 -480,13 +481,13 @@@ print_trns_proc (void *trns_, struct cc else { ds_put_substring (&trns->line, ds_ss (&spec->string)); - if (trns->encoding != LEGACY_NATIVE) + if (0 != strcmp (trns->encoding, LEGACY_NATIVE)) { size_t length = ds_length (&spec->string); char *data = ss_data (ds_tail (&trns->line, length)); - legacy_recode (LEGACY_NATIVE, data, - trns->encoding, data, length); + char *s = recode_string (trns->encoding, LEGACY_NATIVE, data, length); + memcpy (data, s, length); + free (s); } } } diff --combined src/language/dictionary/split-file.c index d2b79c63,0024787f..5d2b42d7 --- a/src/language/dictionary/split-file.c +++ b/src/language/dictionary/split-file.c @@@ -88,17 -88,17 +88,17 @@@ output_split_file_values (const struct for (i = 0; i < split_cnt; i++) { const struct variable *v = split[i]; - char temp_buf[80]; + char *s; const char *val_lab; const struct fmt_spec *print = var_get_print_format (v); - tab_text (t, 0, i + 1, TAB_LEFT | TAT_PRINTF, "%s", var_get_name (v)); + tab_text_format (t, 0, i + 1, TAB_LEFT, "%s", var_get_name (v)); - data_out (case_data (c, v), print, temp_buf); - temp_buf[print->w] = 0; - - tab_text_format (t, 1, i + 1, 0, "%.*s", print->w, temp_buf); + s = data_out (case_data (c, v), dict_get_encoding (dict), print); ++ tab_text_format (t, 1, i + 1, 0, "%.*s", print->w, s); - tab_text (t, 1, i + 1, TAT_PRINTF, "%.*s", print->w, s); + free (s); + val_lab = var_lookup_value_label (v, case_data (c, v)); if (val_lab) tab_text (t, 2, i + 1, TAB_LEFT, val_lab); diff --combined src/language/stats/crosstabs.q index 8347bb5f,e3f54c81..99fa41d9 --- a/src/language/stats/crosstabs.q +++ b/src/language/stats/crosstabs.q @@@ -177,6 -177,7 +177,7 @@@ get_var_range (const struct variable *v struct crosstabs_proc { + const struct dictionary *dict; enum { INTEGER, GENERAL } mode; enum mv_class exclude; bool pivot; @@@ -204,6 -205,7 +205,7 @@@ static voi init_proc (struct crosstabs_proc *proc, struct dataset *ds) { const struct variable *wv = dict_get_weight (dataset_dict (ds)); + proc->dict = dataset_dict (ds); proc->bad_warn = true; proc->variables = NULL; proc->n_variables = 0; @@@ -881,8 -883,8 +883,8 @@@ make_summary_table (struct crosstabs_pr { tab_double (summary, i * 2 + 1, 0, TAB_RIGHT, n[i], &proc->weight_format); - tab_text (summary, i * 2 + 2, 0, TAB_RIGHT | TAT_PRINTF, "%.1f%%", - n[i] / n[2] * 100.); + tab_text_format (summary, i * 2 + 2, 0, TAB_RIGHT, "%.1f%%", + n[i] / n[2] * 100.); } tab_next_row (summary); @@@ -1184,14 -1186,16 +1186,16 @@@ create_crosstab_table (struct crosstabs { const struct variable *var = pt->const_vars[i]; size_t ofs; + char *s = NULL; ds_put_format (&title, ", %s=", var_get_name (var)); /* Insert the formatted value of the variable, then trim leading spaces in what was just inserted. */ ofs = ds_length (&title); - data_out (&pt->const_values[i], var_get_print_format (var), - ds_put_uninit (&title, var_get_width (var))); + s = data_out (&pt->const_values[i], dict_get_encoding (proc->dict), var_get_print_format (var)); + ds_put_cstr (&title, s); + free (s); ds_remove (&title, ofs, ss_cspan (ds_substr (&title, ofs, SIZE_MAX), ss_cstr (" "))); } @@@ -1233,9 -1237,9 +1237,9 @@@ create_chisq_table (struct pivot_table tab_text (chisq, 3, 0, TAB_RIGHT | TAT_TITLE, _("Asymp. Sig. (2-sided)")); tab_text (chisq, 4, 0, TAB_RIGHT | TAT_TITLE, - _("Exact. Sig. (2-sided)")); + _("Exact Sig. (2-sided)")); tab_text (chisq, 5, 0, TAB_RIGHT | TAT_TITLE, - _("Exact. Sig. (1-sided)")); + _("Exact Sig. (1-sided)")); tab_offset (chisq, 0, 1); return chisq; @@@ -1276,8 -1280,8 +1280,8 @@@ create_risk_table (struct pivot_table * tab_title (risk, _("Risk estimate.")); tab_offset (risk, pt->n_vars - 2, 0); - tab_joint_text (risk, 2, 0, 3, 0, TAB_CENTER | TAT_TITLE | TAT_PRINTF, - _("95%% Confidence Interval")); + tab_joint_text_format (risk, 2, 0, 3, 0, TAB_CENTER | TAT_TITLE, + _("95%% Confidence Interval")); tab_text (risk, 0, 1, TAB_LEFT | TAT_TITLE, _("Statistic")); tab_text (risk, 1, 1, TAB_RIGHT | TAT_TITLE, _("Value")); tab_text (risk, 2, 1, TAB_RIGHT | TAT_TITLE, _("Lower")); @@@ -1519,9 -1523,8 +1523,8 @@@ table_value_missing (struct crosstabs_p return; } - s.string = tab_alloc (table, print->w); - data_out (v, print, s.string); - s.length = print->w; + s = ss_cstr (data_out_pool (v, dict_get_encoding (proc->dict), print, + table->container)); if (proc->exclude == MV_NEVER && var_is_num_missing (var, v->f, MV_USER)) s.string[s.length++] = 'M'; while (s.length && *s.string == ' ') @@@ -1554,16 -1557,15 +1557,15 @@@ display_dimensions (struct crosstabs_pr additionally suffixed with a letter `M'. */ static void format_cell_entry (struct tab_table *table, int c, int r, double value, - char suffix, bool mark_missing) + char suffix, bool mark_missing, const struct dictionary *dict) { const struct fmt_spec f = {FMT_F, 10, 1}; union value v; struct substring s; - s.length = 10; - s.string = tab_alloc (table, 16); v.f = value; - data_out (&v, &f, s.string); + s = ss_cstr (data_out_pool (&v, dict_get_encoding (dict), &f, table->container)); + while (*s.string == ' ') { s.length--; @@@ -1649,7 -1651,7 +1651,7 @@@ display_crosstabulation (struct crossta default: NOT_REACHED (); } - format_cell_entry (table, c, i, v, suffix, mark_missing); + format_cell_entry (table, c, i, v, suffix, mark_missing, proc->dict); } mp++; @@@ -1700,7 -1702,7 +1702,7 @@@ NOT_REACHED (); } - format_cell_entry (table, pt->n_cols, 0, v, suffix, mark_missing); + format_cell_entry (table, pt->n_cols, 0, v, suffix, mark_missing, proc->dict); tab_next_row (table); } } @@@ -1750,7 -1752,7 +1752,7 @@@ NOT_REACHED (); } - format_cell_entry (table, c, i, v, suffix, mark_missing); + format_cell_entry (table, c, i, v, suffix, mark_missing, proc->dict); } last_row = i; } @@@ -2060,8 -2062,8 +2062,8 @@@ display_directional (struct crosstabs_p else string = var_get_name (pt->vars[1]); - tab_text (direct, j, 0, TAB_LEFT | TAT_PRINTF, - gettext (stats_names[j][k]), string); + tab_text_format (direct, j, 0, TAB_LEFT, + gettext (stats_names[j][k]), string); } } } diff --combined src/math/interaction.c index 444edbfa,cd151097..7911c8e7 --- a/src/math/interaction.c +++ b/src/math/interaction.c @@@ -149,7 -149,7 +149,7 @@@ interaction_value_create (const struct if (var != NULL) { int val_width = 1; - char *val; + uint8_t *val; result = xmalloc (sizeof (*result)); result->intr = var; @@@ -246,10 -246,12 +246,10 @@@ interaction_case_data (const struct cca { size_t i; size_t n_vars; - const struct variable *intr; const struct variable *member; const union value **vals = NULL; n_vars = interaction_get_n_vars (iv); - intr = interaction_get_variable (iv); vals = xnmalloc (n_vars, sizeof (*vals)); for (i = 0; i < n_vars; i++) diff --combined src/output/table.c index 5686e2bf,04181e44..72edf17f --- a/src/output/table.c +++ b/src/output/table.c @@@ -29,6 -29,7 +29,7 @@@ #include #include #include + #include #include #include #include @@@ -372,6 -373,18 +373,6 @@@ tab_box (struct tab_table *t, int f_h, } } -/* Formats text TEXT and arguments ARGS as indicated in OPT in - TABLE's pool and returns the resultant string. */ -static struct substring -text_format (struct tab_table *table, int opt, const char *text, va_list args) -{ - assert (table != NULL && text != NULL); - - return ss_cstr (opt & TAT_PRINTF - ? pool_vasprintf (table->container, text, args) - : pool_strdup (table->container, text)); -} - /* Set the title of table T to TITLE, which is formatted as if passed to printf(). */ void @@@ -506,7 -519,8 +507,8 @@@ tab_natural_dimensions (struct tab_tabl from V, displayed with format spec F. */ void tab_value (struct tab_table *table, int c, int r, unsigned char opt, - const union value *v, const struct fmt_spec *f) + const union value *v, const struct dictionary *dict, + const struct fmt_spec *f) { char *contents; @@@ -525,11 -539,10 +527,10 @@@ } #endif - contents = pool_alloc (table->container, f->w); - table->cc[c + r * table->cf] = ss_buffer (contents, f->w); - table->ct[c + r * table->cf] = opt; + contents = data_out_pool (v, dict_get_encoding (dict), f, table->container); - data_out (v, f, contents); + table->cc[c + r * table->cf] = ss_cstr (contents); + table->ct[c + r * table->cf] = opt; } /* Sets cell (C,R) in TABLE, with options OPT, to have value VAL @@@ -538,8 -551,7 +539,7 @@@ voi tab_fixed (struct tab_table *table, int c, int r, unsigned char opt, double val, int w, int d) { - char *contents; - char buf[40], *cp; + char *s, *cp; struct fmt_spec f; union value double_value; @@@ -568,17 -580,15 +568,15 @@@ #endif double_value.f = val; - data_out (&double_value, &f, buf); + s = data_out_pool (&double_value, LEGACY_NATIVE, &f, table->container); - cp = buf; - while (isspace ((unsigned char) *cp) && cp < &buf[w]) + cp = s; + while (isspace ((unsigned char) *cp) && cp < &s[w]) cp++; - f.w = w - (cp - buf); + f.w = w - (cp - s); - contents = pool_alloc (table->container, f.w); - table->cc[c + r * table->cf] = ss_buffer (contents, f.w); + table->cc[c + r * table->cf] = ss_buffer (cp, f.w); table->ct[c + r * table->cf] = opt; - memcpy (contents, cp, f.w); } /* Sets cell (C,R) in TABLE, with options OPT, to have value VAL as @@@ -589,11 -599,8 +587,8 @@@ voi tab_double (struct tab_table *table, int c, int r, unsigned char opt, double val, const struct fmt_spec *fmt) { - int w; - char *contents; - char buf[40], *cp; - - union value double_value; + struct substring ss; + union value double_value ; assert (table != NULL); @@@ -622,28 -629,30 +617,23 @@@ #endif double_value.f = val; - data_out (&double_value, fmt, buf); + ss = ss_cstr (data_out_pool (&double_value, LEGACY_NATIVE, fmt, table->container)); - cp = buf; - while (isspace ((unsigned char) *cp) && cp < &buf[fmt->w]) - cp++; - w = fmt->w - (cp - buf); + ss_ltrim (&ss, ss_cstr (" ")); - contents = pool_alloc (table->container, w); - table->cc[c + r * table->cf] = ss_buffer (contents, w); + table->cc[c + r * table->cf] = ss; table->ct[c + r * table->cf] = opt; - memcpy (contents, cp, w); } -/* Sets cell (C,R) in TABLE, with options OPT, to have text value - TEXT. */ -void -tab_text (struct tab_table *table, int c, int r, unsigned opt, const char *text, ...) +static void +do_tab_text (struct tab_table *table, int c, int r, unsigned opt, char *text) { - va_list args; - - assert (table != NULL && text != NULL); - - assert (c >= 0 ); - assert (r >= 0 ); + assert (c >= 0); + assert (r >= 0); assert (c < table->nc); assert (r < table->nr); - #if DEBUGGING if (c + table->col_ofs < 0 || r + table->row_ofs < 0 || c + table->col_ofs >= table->nc @@@ -658,38 -667,21 +648,38 @@@ } #endif - va_start (args, text); - table->cc[c + r * table->cf] = text_format (table, opt, text, args); + table->cc[c + r * table->cf] = ss_cstr (text); table->ct[c + r * table->cf] = opt; - va_end (args); } -/* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with - options OPT to have text value TEXT. */ +/* Sets cell (C,R) in TABLE, with options OPT, to have text value + TEXT. */ void -tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2, - unsigned opt, const char *text, ...) +tab_text (struct tab_table *table, int c, int r, unsigned opt, + const char *text) { - struct tab_joined_cell *j; + do_tab_text (table, c, r, opt, pool_strdup (table->container, text)); +} - assert (table != NULL && text != NULL); +/* Sets cell (C,R) in TABLE, with options OPT, to have text value + FORMAT, which is formatted as if passed to printf. */ +void +tab_text_format (struct tab_table *table, int c, int r, unsigned opt, + const char *format, ...) +{ + va_list args; + + va_start (args, format); + do_tab_text (table, c, r, opt, + pool_vasprintf (table->container, format, args)); + va_end (args); +} + +static void +do_tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2, + unsigned opt, char *text) +{ + struct tab_joined_cell *j; assert (x1 + table->col_ofs >= 0); assert (y1 + table->row_ofs >= 0); @@@ -723,7 -715,14 +713,7 @@@ j->y1 = y1 + table->row_ofs; j->x2 = ++x2 + table->col_ofs; j->y2 = ++y2 + table->row_ofs; - - { - va_list args; - - va_start (args, text); - j->contents = text_format (table, opt, text, args); - va_end (args); - } + j->contents = ss_cstr (text); opt |= TAB_JOIN; @@@ -750,31 -749,6 +740,31 @@@ } } +/* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with + options OPT to have text value TEXT. */ +void +tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2, + unsigned opt, const char *text) +{ + do_tab_joint_text (table, x1, y1, x2, y2, opt, + pool_strdup (table->container, text)); +} + +/* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them + with options OPT to have text value FORMAT, which is formatted + as if passed to printf. */ +void +tab_joint_text_format (struct tab_table *table, int x1, int y1, int x2, int y2, + unsigned opt, const char *format, ...) +{ + va_list args; + + va_start (args, format); + do_tab_joint_text (table, x1, y1, x2, y2, opt, + pool_vasprintf (table->container, format, args)); + va_end (args); +} + /* Sets cell (C,R) in TABLE, with options OPT, to contents STRING. */ void tab_raw (struct tab_table *table, int c, int r, unsigned opt, @@@ -820,41 -794,30 +810,41 @@@ wrap_dim (struct tab_table *t, struct o t->h[0] = tab_natural_height (t, d, 0); } -/* Outputs text BUF as a table with a single cell having cell options +static void +do_tab_output_text (struct tab_table *t, int options, char *text) +{ + do_tab_text (t, 0, 0, options, text); + tab_flags (t, SOMF_NO_TITLE | SOMF_NO_SPACING); + tab_dim (t, options & TAT_NOWRAP ? nowrap_dim : wrap_dim, NULL); + tab_submit (t); +} + +/* Outputs TEXT as a table with a single cell having cell options OPTIONS, which is a combination of the TAB_* and TAT_* - constants. */ + constants. */ void -tab_output_text (int options, const char *buf, ...) +tab_output_text (int options, const char *text) { - struct tab_table *t = tab_create (1, 1, 0); - char *tmp_buf = NULL; - - if (options & TAT_PRINTF) - { - va_list args; + struct tab_table *table = tab_create (1, 1, 0); + do_tab_output_text (table, options, pool_strdup (table->container, text)); +} - va_start (args, buf); - buf = tmp_buf = xvasprintf (buf, args); - va_end (args); - } +/* Outputs FORMAT as a table with a single cell having cell + options OPTIONS, which is a combination of the TAB_* and TAT_* + constants. FORMAT is formatted as if it was passed through + printf. */ +void +tab_output_text_format (int options, const char *format, ...) +{ + struct tab_table *table; + va_list args; - tab_text (t, 0, 0, options & ~TAT_PRINTF, buf); - tab_flags (t, SOMF_NO_TITLE | SOMF_NO_SPACING); - tab_dim (t, options & TAT_NOWRAP ? nowrap_dim : wrap_dim, NULL); - tab_submit (t); + table = tab_create (1, 1, 0); - free (tmp_buf); + va_start (args, format); + do_tab_output_text (table, options, + pool_vasprintf (table->container, format, args)); + va_end (args); } /* Set table flags to FLAGS. */ diff --combined src/output/table.h index 21d3b7bf,e1383613..1748c24c --- a/src/output/table.h +++ b/src/output/table.h @@@ -147,15 -147,18 +147,17 @@@ void tab_box (struct tab_table *, int f enum { TAT_NONE = 0, /* No options. */ - TAT_PRINTF = 0x0100, /* Format the text string with sprintf. */ TAT_TITLE = 0x0200 | TAB_EMPH, /* Title attributes. */ TAT_NOWRAP = 0x0800 /* No text wrap (tab_output_text() only). */ }; /* Cells. */ struct fmt_spec; + struct dictionary; union value; void tab_value (struct tab_table *, int c, int r, unsigned char opt, - const union value *, const struct fmt_spec *); + const union value *, const struct dictionary *dict, + const struct fmt_spec *); void tab_fixed (struct tab_table *, int c, int r, unsigned char opt, double v, int w, int d); @@@ -163,15 -166,11 +165,15 @@@ void tab_double (struct tab_table *, int c, int r, unsigned char opt, double v, const struct fmt_spec *); -void tab_text (struct tab_table *, int c, int r, unsigned opt, - const char *, ...) +void tab_text (struct tab_table *, int c, int r, unsigned opt, const char *); +void tab_text_format (struct tab_table *, int c, int r, unsigned opt, + const char *, ...) PRINTF_FORMAT (5, 6); + void tab_joint_text (struct tab_table *, int x1, int y1, int x2, int y2, - unsigned opt, const char *, ...) + unsigned opt, const char *); +void tab_joint_text_format (struct tab_table *, int x1, int y1, int x2, int y2, + unsigned opt, const char *, ...) PRINTF_FORMAT (7, 8); /* Cell low-level access. */ @@@ -188,8 -187,7 +190,8 @@@ void tab_next_row (struct tab_table *) #define tab_col(TABLE) ((TABLE)->col_ofs) /* Simple output. */ -void tab_output_text (int options, const char *string, ...) +void tab_output_text (int options, const char *string); +void tab_output_text_format (int options, const char *, ...) PRINTF_FORMAT (2, 3); /* Embedding the command name in the output. */