X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fdata-out.c;h=a30e7e703838a31bab2ca5b4eba1b7ecff1899f3;hb=c41cd1fefc98bb4abed33754276d93db9ffe2e0e;hp=02ff06572fabcb1f282c2b9aa51319ee32ae0850;hpb=d0371553a98cd169353bf6d211e375e5ffc3a3bd;p=pspp-builds.git diff --git a/src/data/data-out.c b/src/data/data-out.c index 02ff0657..a30e7e70 100644 --- a/src/data/data-out.c +++ b/src/data/data-out.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,18 +25,19 @@ #include #include -#include "calendar.h" -#include "format.h" -#include "settings.h" -#include "value.h" +#include +#include +#include +#include #include #include #include #include #include -#include #include +#include +#include #include "minmax.h" @@ -61,12 +62,6 @@ static int rounder_width (const struct rounder *, int decimals, static void rounder_format (const struct rounder *, int decimals, char *output); -/* Format of integers in output (SET WIB). */ -static enum integer_format output_integer_format = INTEGER_NATIVE; - -/* Format of reals in output (SET WRB). */ -static enum float_format output_float_format = FLOAT_NATIVE_DOUBLE; - typedef void data_out_converter_func (const union value *, const struct fmt_spec *, char *); @@ -90,64 +85,71 @@ static void output_binary_integer (uint64_t, int bytes, enum integer_format, char *); static void output_hex (const void *, size_t bytes, char *); -/* Converts the INPUT value into printable form in the exactly - FORMAT->W characters in OUTPUT according to format - specification FORMAT. The output is recoded from native form - into the given legacy character ENCODING. No null terminator - is appended to the buffer. */ -void -data_out_legacy (const union value *input, enum legacy_encoding encoding, - const struct fmt_spec *format, char *output) -{ - static data_out_converter_func *const converters[FMT_NUMBER_OF_FORMATS] = + +static data_out_converter_func *const converters[FMT_NUMBER_OF_FORMATS] = { #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) output_##METHOD, #include "format.def" }; +/* Similar to data_out. Additionally recodes the output from + native form into the given legacy character ENCODING. + OUTPUT must be provided by the caller and must be at least + FORMAT->w long. No null terminator is appended to OUTPUT. +*/ +void +data_out_legacy (const union value *input, const char *encoding, + const struct fmt_spec *format, char *output) +{ assert (fmt_check_output (format)); converters[format->type] (input, format, output); - if (encoding != LEGACY_NATIVE + if (0 != strcmp (encoding, C_ENCODING) && fmt_get_category (format->type) != FMT_CAT_BINARY) - legacy_recode (LEGACY_NATIVE, output, encoding, output, format->w); + { + char *s = recode_string (encoding, C_ENCODING, output, format->w ); + memcpy (output, s, format->w); + free (s); + } } -/* Same as data_out_legacy with ENCODING set to LEGACY_NATIVE. */ -void -data_out (const union value *value, const struct fmt_spec *format, - char *output) -{ - return data_out_legacy (value, LEGACY_NATIVE, format, output); -} +/* Converts the INPUT value into a UTF8 encoded string, according + to format specification FORMAT. -/* Returns the current output integer format. */ -enum integer_format -data_out_get_integer_format (void) -{ - return output_integer_format; -} + VALUE must be the correct width for FORMAT, that is, its + width must be fmt_var_width(FORMAT). -/* Sets the output integer format to INTEGER_FORMAT. */ -void -data_out_set_integer_format (enum integer_format integer_format) -{ - output_integer_format = integer_format; -} + ENCODING must be the encoding of INPUT. Normally this can + be obtained by calling dict_get_encoding on the dictionary + with which INPUT is associated. -/* Returns the current output float format. */ -enum float_format -data_out_get_float_format (void) + The return value is dynamically allocated, and must be freed + by the caller. If POOL is non-null, then the return value is + allocated on that pool. +*/ +char * +data_out_pool (const union value *input, const char *encoding, + const struct fmt_spec *format, struct pool *pool) { - return output_float_format; + char *output; + char *t ; + assert (fmt_check_output (format)); + + output = xmalloc (format->w + 1); + + converters[format->type] (input, format, output); + + t = recode_string_pool (UTF8, encoding, output, format->w, pool); + free (output); + return t; } -/* Sets the output float format to FLOAT_FORMAT. */ -void -data_out_set_float_format (enum float_format float_format) +char * +data_out (const union value *input, const char *encoding, const struct fmt_spec *format) { - output_float_format = float_format; + return data_out_pool (input, encoding, format, NULL); } + /* Main conversion functions. */ @@ -199,6 +201,8 @@ output_N (const union value *input, const struct fmt_spec *format, else output_overflow (format, output); } + + output[format->w] = '\0'; } /* Outputs Z format. */ @@ -222,6 +226,7 @@ output_Z (const union value *input, const struct fmt_spec *format, *p = "}JKLMNOPQR"[*p - '0']; } memcpy (output, buf, format->w); + output[format->w] = '\0'; } } @@ -261,9 +266,12 @@ output_IB (const union value *input, const struct fmt_spec *format, uint64_t integer = fabs (number); if (number < 0) integer = -integer; - output_binary_integer (integer, format->w, output_integer_format, + output_binary_integer (integer, format->w, + settings_get_output_integer_format (), output); } + + output[format->w] = '\0'; } /* Outputs PIB format. */ @@ -276,7 +284,10 @@ output_PIB (const union value *input, const struct fmt_spec *format, || number < 0 || number >= power256 (format->w)) memset (output, 0, format->w); else - output_binary_integer (number, format->w, output_integer_format, output); + output_binary_integer (number, format->w, + settings_get_output_integer_format (), output); + + output[format->w] = '\0'; } /* Outputs PIBHEX format. */ @@ -295,6 +306,7 @@ output_PIBHEX (const union value *input, const struct fmt_spec *format, output_binary_integer (number, format->w / 2, INTEGER_MSB_FIRST, tmp); output_hex (tmp, format->w / 2, output); } + } /* Outputs RB format. */ @@ -304,6 +316,8 @@ output_RB (const union value *input, const struct fmt_spec *format, { double d = input->f; memcpy (output, &d, format->w); + + output[format->w] = '\0'; } /* Outputs RBHEX format. */ @@ -312,6 +326,7 @@ output_RBHEX (const union value *input, const struct fmt_spec *format, char *output) { double d = input->f; + output_hex (&d, format->w / 2, output); } @@ -367,7 +382,7 @@ output_date (const union value *input, const struct fmt_spec *format, p += sprintf (p, "%02d", month); else { - static const char *months[12] = + static const char *const months[12] = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC", @@ -387,7 +402,8 @@ output_date (const union value *input, const struct fmt_spec *format, } else { - int offset = year - get_epoch (); + int epoch = settings_get_epoch (); + int offset = year - epoch; if (offset < 0 || offset > 99) goto overflow; p += sprintf (p, "%02d", abs (year) % 100); @@ -427,11 +443,11 @@ output_date (const union value *input, const struct fmt_spec *format, int d = MIN (format->d, excess_width - 4); int w = d + 3; sprintf (p, ":%0*.*f", w, d, number); - if (fmt_decimal_char (FMT_F) != '.') + if (settings_get_decimal_char (FMT_F) != '.') { char *cp = strchr (p, '.'); if (cp != NULL) - *cp = fmt_decimal_char (FMT_F); + *cp = settings_get_decimal_char (FMT_F); } p += strlen (p); } @@ -446,7 +462,8 @@ output_date (const union value *input, const struct fmt_spec *format, } } - buf_copy_lpad (output, format->w, tmp, p - tmp); + buf_copy_lpad (output, format->w, tmp, p - tmp, ' '); + output[format->w] = '\0'; return; overflow: @@ -463,20 +480,25 @@ static void output_WKDAY (const union value *input, const struct fmt_spec *format, char *output) { - static const char *weekdays[7] = + static const char *const weekdays[7] = { "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", }; if (input->f >= 1 && input->f < 8) - buf_copy_str_rpad (output, format->w, weekdays[(int) input->f - 1]); + { + buf_copy_str_rpad (output, format->w, + weekdays[(int) input->f - 1], ' '); + output[format->w] = '\0'; + } else { if (input->f != SYSMIS) msg (ME, _("Weekday number %f is not between 1 and 7."), input->f); output_missing (format, output); } + } /* Outputs MONTH format. */ @@ -484,20 +506,24 @@ static void output_MONTH (const union value *input, const struct fmt_spec *format, char *output) { - static const char *months[12] = + static const char *const months[12] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER", }; if (input->f >= 1 && input->f < 13) - buf_copy_str_rpad (output, format->w, months[(int) input->f - 1]); + { + buf_copy_str_rpad (output, format->w, months[(int) input->f - 1], ' '); + output[format->w] = '\0'; + } else { if (input->f != SYSMIS) msg (ME, _("Month number %f is not between 1 and 12."), input->f); output_missing (format, output); } + } /* Outputs A format. */ @@ -505,7 +531,8 @@ static void output_A (const union value *input, const struct fmt_spec *format, char *output) { - memcpy (output, input->s, format->w); + memcpy (output, value_str (input, format->w), format->w); + output[format->w] = '\0'; } /* Outputs AHEX format. */ @@ -513,7 +540,7 @@ static void output_AHEX (const union value *input, const struct fmt_spec *format, char *output) { - output_hex (input->s, format->w, output); + output_hex (value_str (input, format->w), format->w / 2, output); } /* Decimal and scientific formatting. */ @@ -544,7 +571,9 @@ static bool output_decimal (const struct rounder *r, const struct fmt_spec *format, bool require_affixes, char *output) { - const struct fmt_number_style *style = fmt_get_style (format->type); + const struct fmt_number_style *style = + settings_get_style (format->type); + int decimals; for (decimals = format->d; decimals >= 0; decimals--) @@ -573,9 +602,9 @@ output_decimal (const struct rounder *r, const struct fmt_spec *format, the negative suffix, plus (if negative) the negative prefix. */ width = rounder_width (r, decimals, &integer_digits, &add_neg_prefix); - width += ss_length (style->neg_suffix); + width += strlen (style->neg_suffix.s); if (add_neg_prefix) - width += ss_length (style->neg_prefix); + width += strlen (style->neg_prefix.s); if (width > format->w) continue; @@ -605,10 +634,9 @@ output_decimal (const struct rounder *r, const struct fmt_spec *format, if (format->w > width) p = mempset (p, ' ', format->w - width); if (add_neg_prefix) - p = mempcpy (p, ss_data (style->neg_prefix), - ss_length (style->neg_prefix)); + p = stpcpy (p, style->neg_prefix.s); if (add_affixes) - p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix)); + p = stpcpy (p, style->prefix.s); if (!add_grouping) p = mempcpy (p, magnitude, integer_digits); else @@ -627,12 +655,11 @@ output_decimal (const struct rounder *r, const struct fmt_spec *format, p = mempcpy (p, &magnitude[integer_digits + 1], decimals); } if (add_affixes) - p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix)); + p = stpcpy (p, style->suffix.s); if (add_neg_prefix) - p = mempcpy (p, ss_data (style->neg_suffix), - ss_length (style->neg_suffix)); + p = stpcpy (p, style->neg_suffix.s); else - p = mempset (p, ' ', ss_length (style->neg_suffix)); + p = mempset (p, ' ', strlen (style->neg_suffix.s)); assert (p == output + format->w); return true; @@ -646,16 +673,17 @@ static bool output_scientific (double number, const struct fmt_spec *format, bool require_affixes, char *output) { - const struct fmt_number_style *style = fmt_get_style (format->type); + const struct fmt_number_style *style = + settings_get_style (format->type); int width; int fraction_width; bool add_affixes; char buf[64], *p; /* Allocate minimum required space. */ - width = 6 + ss_length (style->neg_suffix); + width = 6 + strlen (style->neg_suffix.s); if (number < 0) - width += ss_length (style->neg_prefix); + width += strlen (style->neg_prefix.s); if (width > format->w) return false; @@ -678,10 +706,9 @@ output_scientific (double number, const struct fmt_spec *format, if (width < format->w) p = mempset (p, ' ', format->w - width); if (number < 0) - p = mempcpy (p, ss_data (style->neg_prefix), - ss_length (style->neg_prefix)); + p = stpcpy (p, style->neg_prefix.s); if (add_affixes) - p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix)); + p = stpcpy (p, style->prefix.s); if (fraction_width > 0) sprintf (p, "%#.*E", fraction_width - 1, fabs (number)); else @@ -708,15 +735,15 @@ output_scientific (double number, const struct fmt_spec *format, /* Add suffixes. */ p = strchr (p, '\0'); if (add_affixes) - p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix)); + p = stpcpy (p, style->suffix.s); if (number < 0) - p = mempcpy (p, ss_data (style->neg_suffix), - ss_length (style->neg_suffix)); + p = stpcpy (p, style->neg_suffix.s); else - p = mempset (p, ' ', ss_length (style->neg_suffix)); + p = mempset (p, ' ', strlen (style->neg_suffix.s)); assert (p == buf + format->w); memcpy (output, buf, format->w); + output[format->w] = '\0'; return true; } @@ -962,10 +989,12 @@ output_infinite (double number, const struct fmt_spec *format, char *output) else s = "Unknown"; - buf_copy_str_lpad (output, format->w, s); + buf_copy_str_lpad (output, format->w, s, ' '); } else output_overflow (format, output); + + output[format->w] = '\0'; } /* Formats OUTPUT as a missing value for the given FORMAT. */ @@ -983,6 +1012,8 @@ output_missing (const struct fmt_spec *format, char *output) } else output[format->w - 1] = '.'; + + output[format->w] = '\0'; } /* Formats OUTPUT for overflow given FORMAT. */ @@ -990,6 +1021,7 @@ static void output_overflow (const struct fmt_spec *format, char *output) { memset (output, '*', format->w); + output[format->w] = '\0'; } /* Converts the integer part of NUMBER to a packed BCD number @@ -1004,6 +1036,8 @@ output_bcd_integer (double number, int digits, char *output) char decimal[64]; assert (digits < sizeof decimal); + + output[DIV_RND_UP (digits, 2)] = '\0'; if (number != SYSMIS && number >= 0. && number < power10 (digits) @@ -1053,4 +1087,5 @@ output_hex (const void *data_, size_t bytes, char *output) *output++ = hex_digits[data[i] >> 4]; *output++ = hex_digits[data[i] & 15]; } + *output = '\0'; }