/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
#include <stdlib.h>
#include <time.h>
#include "calendar.h"
+#include <libpspp/assertion.h>
#include <libpspp/message.h>
#include "format.h"
#include <libpspp/magic.h>
bool
data_out (char *s, const struct fmt_spec *fp, const union value *v)
{
- int cat = formats[fp->type].cat;
int ok;
- assert (check_output_specifier (fp, 0));
- if (!(cat & FCAT_STRING))
+ assert (fmt_check_output (fp));
+ if (fmt_is_numeric (fp->type))
{
- /* Numeric formatting. */
+ enum fmt_category category = fmt_get_category (fp->type);
double number = v->f;
/* Handle SYSMIS turning into blanks. */
- if ((cat & FCAT_BLANKS_SYSMIS) && number == SYSMIS)
+ if (!(category & (FMT_CAT_CUSTOM | FMT_CAT_BINARY | FMT_CAT_HEXADECIMAL))
+ && number == SYSMIS)
{
memset (s, ' ', fp->w);
s[fp->w - fp->d - 1] = '.';
}
/* Handle decimal shift. */
- if ((cat & FCAT_SHIFT_DECIMAL) && number != SYSMIS && fp->d)
+ if ((category & (FMT_CAT_LEGACY | FMT_CAT_BINARY))
+ && number != SYSMIS
+ && fp->d)
number *= pow (10.0, fp->d);
switch (fp->type)
break;
case FMT_A:
- assert (0);
- abort ();
+ NOT_REACHED ();
case FMT_AHEX:
- assert (0);
- abort ();
+ NOT_REACHED ();
case FMT_IB:
ok = convert_IB (s, fp, number);
break;
default:
- assert (0);
- abort ();
+ NOT_REACHED ();
}
}
else
break;
default:
- assert (0);
- abort ();
+ NOT_REACHED ();
}
}
return ok;
}
-
-/* Converts V into S in F format with width W and D decimal places,
- then deletes trailing zeros. S is not null-terminated. */
-void
-num_to_string (double v, char *s, int w, int d)
-{
- struct fmt_spec f = make_output_format (FMT_F, w, d);
- convert_F (s, &f, v);
-}
\f
/* Main conversion functions. */
/* The C locale always uses a period `.' as a decimal point.
Translate to comma if necessary. */
- if ((get_decimal() == ',' && fp->type != FMT_DOT)
- || (get_decimal() == '.' && fp->type == FMT_DOT))
+ if (fmt_decimal_char (fp->type) != '.')
{
char *cp = strchr (buf, '.');
if (cp)
- *cp = ',';
+ *cp = fmt_decimal_char (fp->type);
}
memcpy (dst, buf, fp->w);
static int
convert_Z (char *dst, const struct fmt_spec *fp, double number)
{
- static int warned = 0;
+ static bool warned = false;
if (!warned)
{
static int
convert_A (char *dst, const struct fmt_spec *fp, const char *string)
{
- memcpy (dst, string, fp->w);
+ memcpy(dst, string, fp->w);
return 1;
}
}
break;
default:
- assert (0);
+ NOT_REACHED ();
}
if (buf[0] == 0)
if (i % 3 == 0 && n_digits > i && n_items > n_reserved)
{
n_items--;
- *dst++ = fp->type == FMT_COMMA ? get_grouping() : get_decimal();
+ *dst++ = fmt_grouping_char (fp->type);
}
*dst++ = *sp++;
}
static int
try_CCx (char *dst, const struct fmt_spec *fp, double number)
{
- const struct custom_currency *cc = get_cc(fp->type - FMT_CCA);
+ const struct fmt_number_style *style = fmt_get_style (fp->type);
struct fmt_spec f;
/* Determine length available, decimal character for number
proper. */
- f.type = cc->decimal == get_decimal () ? FMT_COMMA : FMT_DOT;
- f.w = fp->w - strlen (cc->prefix) - strlen (cc->suffix);
+ f.type = style->decimal == fmt_decimal_char (FMT_COMMA) ? FMT_COMMA : FMT_DOT;
+ f.w = fp->w - fmt_affix_width (style);
if (number < 0)
- f.w -= strlen (cc->neg_prefix) + strlen (cc->neg_suffix) - 1;
+ f.w -= fmt_neg_affix_width (style) - 1;
else
/* Convert -0 to +0. */
number = fabs (number);
/* Postprocess back into buf. */
cp = buf;
if (number < 0)
- cp = stpcpy (cp, cc->neg_prefix);
- cp = stpcpy (cp, cc->prefix);
+ cp = mempcpy (cp, ss_data (style->neg_prefix),
+ ss_length (style->neg_prefix));
+ cp = mempcpy (cp, ss_data (style->prefix), ss_length (style->prefix));
{
char *bp = buf2;
while (*bp == ' ')
memcpy (cp, bp, f.w - (bp - buf2));
cp += f.w - (bp - buf2);
}
- cp = stpcpy (cp, cc->suffix);
+ cp = mempcpy (cp, ss_data (style->suffix), ss_length (style->suffix));
if (number < 0)
- cp = stpcpy (cp, cc->neg_suffix);
+ cp = mempcpy (cp, ss_data (style->neg_suffix),
+ ss_length (style->neg_suffix));
/* Copy into dst. */
assert (cp - buf <= fp->w);
avoids wasting too much time formatting more
decimal places on the first try. */
int result = format_and_round (dst, number, fp, fp->d + 2);
+
if (result >= 0)
return result;
digits of the fraction.
Right-justify the integer part and sign. */
dst[0] = ' ';
- memcpy (dst + 1, buf, fp->w);
+ memcpy (dst + 1, buf, fp->w - 1);
return 1;
}