1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
30 #include "julcal/julcal.h"
38 #include "debug-print.h"
40 /* In older versions, numbers got their trailing zeros stripped.
41 Newer versions leave them on when there's room. Comment this next
42 line out for retro styling. */
45 /* Public functions. */
47 typedef int convert_func (char *, const struct fmt_spec *,
50 static convert_func convert_F, convert_N, convert_E, convert_F_plus;
51 static convert_func convert_Z, convert_A, convert_AHEX, convert_IB;
52 static convert_func convert_P, convert_PIB, convert_PIBHEX, convert_PK;
53 static convert_func convert_RB, convert_RBHEX, convert_CCx, convert_date;
54 static convert_func convert_time, convert_WKDAY, convert_MONTH;
55 static convert_func try_F;
57 /* Converts binary value V into printable form in string S according
58 to format specification FP. The string as written has exactly
59 FP->W characters. It is not null-terminated. Returns 1 on
60 success, 0 on failure. */
62 data_out (char *s, const struct fmt_spec *fp, const union value *v)
67 int cat = formats[fp->type].cat;
68 if ((cat & FCAT_BLANKS_SYSMIS) && v->f == SYSMIS)
70 memset (s, ' ', fp->w);
71 s[fp->w - fp->d - 1] = '.';
74 if ((cat & FCAT_SHIFT_DECIMAL) && v->f != SYSMIS && fp->d)
76 tmp_val.f = v->f * pow (10.0, fp->d);
82 static convert_func *const handlers[FMT_NUMBER_OF_FORMATS] =
84 convert_F, convert_N, convert_E, convert_F_plus,
85 convert_F_plus, convert_F_plus, convert_F_plus,
86 convert_Z, convert_A, convert_AHEX, convert_IB, convert_P, convert_PIB,
87 convert_PIBHEX, convert_PK, convert_RB, convert_RBHEX,
88 convert_CCx, convert_CCx, convert_CCx, convert_CCx, convert_CCx,
89 convert_date, convert_date, convert_date, convert_date, convert_date,
90 convert_date, convert_date, convert_date, convert_date,
91 convert_time, convert_time,
92 convert_WKDAY, convert_MONTH,
95 return handlers[fp->type] (s, fp, v);
99 /* Converts V into S in F format with width W and D decimal places,
100 then deletes trailing zeros. S is not null-terminated. */
102 num_to_string (double v, char *s, int w, int d)
104 /* Dummies to pass to convert_F. */
109 /* Pointer to `.' in S. */
112 /* Pointer to `E' in S. */
115 /* Number of characters to delete. */
123 /* Cut out the jokers. */
131 memcpy (temp, "NaN", 3);
136 memcpy (temp, "+Infinity", 9);
143 memcpy (temp, _("Unknown"), 7);
149 memset (s, ' ', pad);
160 decp = memchr (s, set_decimal, w);
164 /* If there's an `E' we can only delete 0s before the E. */
165 expp = memchr (s, 'E', w);
168 while (expp[-n - 1] == '0')
170 if (expp[-n - 1] == set_decimal)
172 memmove (&s[n], s, expp - s - n);
177 /* Otherwise delete all trailing 0s. */
179 while (s[w - n] == '0')
181 if (s[w - n] != set_decimal)
183 /* Avoid stripping `.0' to `'. */
184 if (w == n || !isdigit ((unsigned char) s[w - n - 1]))
189 memmove (&s[n], s, w - n);
194 /* Main conversion functions. */
196 static void insert_commas (char *dst, const char *src,
197 const struct fmt_spec *fp);
198 static int year4 (int year);
199 static int try_CCx (char *s, const struct fmt_spec *fp, double v);
202 #error Write your own floating-point output routines.
207 Some of the routines in this file are likely very specific to
208 base-2 representation of floating-point numbers, most notably the
209 routines that use frexp() or ldexp(). These attempt to extract
210 individual digits by setting the base-2 exponent and
211 multiplying/dividing by powers of 2. In base-2 numeration systems,
212 this just nudges the exponent up or down, but in base-10 floating
213 point, such multiplications/division can cause catastrophic loss of
216 The author has never personally used a machine that didn't use
217 binary floating point formats, so he is unwilling, and perhaps
218 unable, to code around this "problem". */
220 /* Converts a number between 0 and 15 inclusive to a `hexit'
222 #define MAKE_HEXIT(X) ("0123456789ABCDEF"[X])
224 /* Table of powers of 10. */
225 static const double power10[] =
228 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, 1e10,
229 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20,
230 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30,
231 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, 1e40,
234 /* Handles F format. */
236 convert_F (char *dst, const struct fmt_spec *fp, const union value *v)
238 if (!try_F (dst, fp, v))
239 convert_E (dst, fp, v);
243 /* Handles N format. */
245 convert_N (char *dst, const struct fmt_spec *fp, const union value *v)
247 double d = floor (v->f);
249 if (d < 0 || d == SYSMIS)
251 msg (ME, _("The N output format cannot be used to output a "
252 "negative number or the system-missing value."));
256 if (d < power10[fp->w])
259 sprintf (buf, "%0*.0f", fp->w, v->f);
260 memcpy (dst, buf, fp->w);
263 memset (dst, '*', fp->w);
268 /* Handles E format. Also operates as fallback for some other
271 convert_E (char *dst, const struct fmt_spec *fp, const union value *v)
273 /* Temporary buffer. */
276 /* Ranged number of decimal places. */
279 /* Check that the format is width enough.
280 Although PSPP generally checks this, convert_E() can be called as
281 a fallback from other formats which do not check. */
284 memset (dst, '*', fp->w);
288 /* Put decimal places in usable range. */
289 d = min (fp->d, fp->w - 6);
294 sprintf (buf, "%*.*E", fp->w, d, v->f);
296 /* What we do here is force the exponent part to have four
297 characters whenever possible. That is, 1.00E+99 is okay (`E+99')
298 but 1.00E+100 (`E+100') must be coerced to 1.00+100 (`+100'). On
299 the other hand, 1.00E1000 (`E+100') cannot be canonicalized.
300 Note that ANSI C guarantees at least two digits in the
302 if (fabs (v->f) > 1e99)
304 /* Pointer to the `E' in buf. */
307 cp = strchr (buf, 'E');
310 /* Exponent better not be bigger than an int. */
311 int exp = atoi (cp + 1);
313 if (abs (exp) > 99 && abs (exp) < 1000)
315 /* Shift everything left one place: 1.00e+100 -> 1.00+100. */
321 else if (abs (exp) >= 1000)
322 memset (buf, '*', fp->w);
326 /* The C locale always uses a period `.' as a decimal point.
327 Translate to comma if necessary. */
328 if ((set_decimal == ',' && fp->type != FMT_DOT)
329 || (set_decimal == '.' && fp->type == FMT_DOT))
331 char *cp = strchr (buf, '.');
336 memcpy (dst, buf, fp->w);
340 /* Handles COMMA, DOT, DOLLAR, and PCT formats. */
342 convert_F_plus (char *dst, const struct fmt_spec *fp, const union value *v)
346 if (try_F (buf, fp, v))
347 insert_commas (dst, buf, fp);
349 convert_E (dst, fp, v);
355 convert_Z (char *dst, const struct fmt_spec *fp, const union value *v)
357 static int warned = 0;
362 _("Quality of zoned decimal (Z) output format code is suspect. Check your results. Report bugs to %s."),
369 msg (ME, _("The system-missing value cannot be output as a zoned "
379 d = fabs (floor (v->f));
380 if (d >= power10[fp->w])
382 msg (ME, _("Number %g too big to fit in field with format Z%d.%d."),
387 sprintf (buf, "%*.0f", fp->w, v->f);
388 for (i = 0; i < fp->w; i++)
389 dst[i] = (buf[i] - '0') | 0xf0;
391 dst[fp->w - 1] &= 0xdf;
398 convert_A (char *dst, const struct fmt_spec *fp, const union value *v)
400 memcpy (dst, v->c, fp->w);
405 convert_AHEX (char *dst, const struct fmt_spec *fp, const union value *v)
409 for (i = 0; i < fp->w / 2; i++)
411 ((unsigned char *) dst)[i * 2] = MAKE_HEXIT ((v->c[i]) >> 4);
412 ((unsigned char *) dst)[i * 2 + 1] = MAKE_HEXIT ((v->c[i]) & 0xf);
419 convert_IB (char *dst, const struct fmt_spec *fp, const union value *v)
421 /* Strategy: Basically the same as convert_PIBHEX() but with base
422 256. Then it's necessary to negate the two's-complement result if
425 /* Used for constructing the two's-complement result. */
428 /* Fraction (mantissa). */
434 /* Difference between exponent and (-8*fp->w-1). */
440 /* Make the exponent (-8*fp->w-1). */
441 frac = frexp (fabs (v->f), &exp);
442 diff = exp - (-8 * fp->w - 1);
444 frac *= ldexp (1.0, diff);
446 /* Extract each base-256 digit. */
447 for (i = 0; i < fp->w; i++)
451 temp[i] = floor (frac);
454 /* Perform two's-complement negation if v->f is negative. */
457 /* Perform NOT operation. */
458 for (i = 0; i < fp->w; i++)
460 /* Add 1 to the whole number. */
461 for (i = fp->w - 1; i >= 0; i--)
468 memcpy (dst, temp, fp->w);
469 #ifndef WORDS_BIGENDIAN
470 mm_reverse (dst, fp->w);
477 convert_P (char *dst, const struct fmt_spec *fp, const union value *v)
479 /* Buffer for v->f*2-1 characters + a decimal point if library is
480 not quite compliant + a null. */
486 /* Main extraction. */
487 sprintf (buf, "%0*.0f", fp->w * 2 - 1, floor (fabs (v->f)));
489 for (i = 0; i < fp->w; i++)
490 ((unsigned char *) dst)[i]
491 = ((buf[i * 2] - '0') << 4) + buf[i * 2 + 1] - '0';
494 dst[fp->w - 1] &= 0xf0;
496 dst[fp->w - 1] |= 0xf;
498 dst[fp->w - 1] |= 0xd;
504 convert_PIB (char *dst, const struct fmt_spec *fp, const union value *v)
506 /* Strategy: Basically the same as convert_IB(). */
508 /* Fraction (mantissa). */
514 /* Difference between exponent and (-8*fp->w). */
520 /* Make the exponent (-8*fp->w). */
521 frac = frexp (fabs (v->f), &exp);
522 diff = exp - (-8 * fp->w);
524 frac *= ldexp (1.0, diff);
526 /* Extract each base-256 digit. */
527 for (i = 0; i < fp->w; i++)
531 ((unsigned char *) dst)[i] = floor (frac);
533 #ifndef WORDS_BIGENDIAN
534 mm_reverse (dst, fp->w);
541 convert_PIBHEX (char *dst, const struct fmt_spec *fp, const union value *v)
543 /* Strategy: Use frexp() to create a normalized result (but mostly
544 to find the base-2 exponent), then change the base-2 exponent to
545 (-4*fp->w) using multiplication and division by powers of two.
546 Extract each hexit by multiplying by 16. */
548 /* Fraction (mantissa). */
554 /* Difference between exponent and (-4*fp->w). */
560 /* Make the exponent (-4*fp->w). */
561 frac = frexp (fabs (v->f), &exp);
562 diff = exp - (-4 * fp->w);
564 frac *= ldexp (1.0, diff);
566 /* Extract each hexit. */
567 for (i = 0; i < fp->w; i++)
571 *dst++ = MAKE_HEXIT ((int) floor (frac));
578 convert_PK (char *dst, const struct fmt_spec *fp, const union value *v)
580 /* Buffer for v->f*2 characters + a decimal point if library is not
581 quite compliant + a null. */
587 /* Main extraction. */
588 sprintf (buf, "%0*.0f", fp->w * 2, floor (fabs (v->f)));
590 for (i = 0; i < fp->w; i++)
591 ((unsigned char *) dst)[i]
592 = ((buf[i * 2] - '0') << 4) + buf[i * 2 + 1] - '0';
598 convert_RB (char *dst, const struct fmt_spec *fp, const union value *v)
608 memcpy (dst, u.c, fp->w);
614 convert_RBHEX (char *dst, const struct fmt_spec *fp, const union value *v)
626 for (i = 0; i < fp->w / 2; i++)
628 *dst++ = MAKE_HEXIT (u.c[i] >> 4);
629 *dst++ = MAKE_HEXIT (u.c[i] & 15);
636 convert_CCx (char *dst, const struct fmt_spec *fp, const union value *v)
638 if (try_CCx (dst, fp, v->f))
648 return convert_F (dst, &f, v);
653 convert_date (char *dst, const struct fmt_spec *fp, const union value *v)
655 static const char *months[12] =
657 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
658 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
662 int month, day, year;
664 julian_to_calendar (v->f / 86400., &year, &month, &day);
669 sprintf (buf, "%02d-%s-%04d", day, months[month - 1], year);
671 sprintf (buf, "%02d-%s-%02d", day, months[month - 1], year % 100);
675 sprintf (buf, "%02d.%02d.%04d", day, month, year);
677 sprintf (buf, "%02d.%02d.%02d", day, month, year % 100);
681 sprintf (buf, "%04d/%02d/%02d", year, month, day);
683 sprintf (buf, "%02d/%02d/%02d", year % 100, month, day);
687 sprintf (buf, "%02d/%02d/%04d", month, day, year);
689 sprintf (buf, "%02d/%02d/%02d", month, day, year % 100);
693 int yday = (v->f / 86400.) - calendar_to_julian (year, 1, 1) + 1;
698 sprintf (buf, "%04d%03d", year, yday);
701 sprintf (buf, "%02d%03d", year % 100, yday);
706 sprintf (buf, "%d Q% 04d", (month - 1) / 3 + 1, year);
708 sprintf (buf, "%d Q% 02d", (month - 1) / 3 + 1, year % 100);
712 sprintf (buf, "%s% 04d", months[month - 1], year);
714 sprintf (buf, "%s% 02d", months[month - 1], year % 100);
718 int yday = (v->f / 86400.) - calendar_to_julian (year, 1, 1) + 1;
721 sprintf (buf, "%02d WK% 04d", (yday - 1) / 7 + 1, year);
723 sprintf (buf, "%02d WK% 02d", (yday - 1) / 7 + 1, year % 100);
730 cp = spprintf (buf, "%02d-%s-%04d %02d:%02d",
731 day, months[month - 1], year,
732 (int) fmod (floor (v->f / 60. / 60.), 24.),
733 (int) fmod (floor (v->f / 60.), 60.));
738 if (fp->w >= 22 && fp->d > 0)
740 d = min (fp->d, fp->w - 21);
749 cp = spprintf (cp, ":%0*.*f", w, d, fmod (v->f, 60.));
759 st_bare_pad_copy (dst, buf, fp->w);
764 convert_time (char *dst, const struct fmt_spec *fp, const union value *v)
772 if (fabs (v->f) > 1e20)
774 msg (ME, _("Time value %g too large in magnitude to convert to "
775 "alphanumeric time."), v->f);
783 *cp++ = '-', time = -time;
784 if (fp->type == FMT_DTIME)
786 double days = floor (time / 60. / 60. / 24.);
787 cp = spprintf (temp_buf, "%02.0f ", days);
788 time = time - days * 60. * 60. * 24.;
794 cp = spprintf (cp, "%02.0f:%02.0f",
795 fmod (floor (time / 60. / 60.), 24.),
796 fmod (floor (time / 60.), 60.));
802 if (width >= 10 && fp->d >= 0 && fp->d != 0)
803 d = min (fp->d, width - 9), w = 3 + d;
807 cp = spprintf (cp, ":%0*.*f", w, d, fmod (time, 60.));
809 st_bare_pad_copy (dst, temp_buf, fp->w);
815 convert_WKDAY (char *dst, const struct fmt_spec *fp, const union value *v)
817 static const char *weekdays[7] =
819 "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
820 "THURSDAY", "FRIDAY", "SATURDAY",
827 msg (ME, _("Weekday index %d does not lie between 1 and 7."), x);
830 st_bare_pad_copy (dst, weekdays[x - 1], fp->w);
836 convert_MONTH (char *dst, const struct fmt_spec *fp, const union value *v)
838 static const char *months[12] =
840 "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
841 "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",
848 msg (ME, _("Month index %d does not lie between 1 and 12."), x);
852 st_bare_pad_copy (dst, months[x - 1], fp->w);
857 /* Helper functions. */
859 /* Copies SRC to DST, inserting commas and dollar signs as appropriate
860 for format spec *FP. */
862 insert_commas (char *dst, const char *src, const struct fmt_spec *fp)
864 /* Number of leading spaces in the number. This is the amount of
865 room we have for inserting commas and dollar signs. */
868 /* Number of digits before the decimal point. This is used to
869 determine the Number of commas to insert. */
872 /* Number of commas to insert. */
875 /* Number of items ,%$ to insert. */
878 /* Number of n_items items not to use for commas. */
881 /* Digit iterator. */
884 /* Source pointer. */
887 /* Count spaces and digits. */
889 while (sp < src + fp->w && *sp == ' ')
896 while (sp + n_digits < src + fp->w && isdigit ((unsigned char) sp[n_digits]))
898 n_commas = (n_digits - 1) / 3;
899 n_items = n_commas + (fp->type == FMT_DOLLAR || fp->type == FMT_PCT);
901 /* Check whether we have enough space to do insertions. */
902 if (!n_spaces || !n_items)
904 memcpy (dst, src, fp->w);
907 if (n_items > n_spaces)
912 memcpy (dst, src, fp->w);
917 /* Put spaces at the beginning if there's extra room. */
918 if (n_spaces > n_items)
920 memset (dst, ' ', n_spaces - n_items);
921 dst += n_spaces - n_items;
924 /* Insert $ and reserve space for %. */
926 if (fp->type == FMT_DOLLAR)
931 else if (fp->type == FMT_PCT)
934 /* Copy negative sign and digits, inserting commas. */
935 if (sp - src > n_spaces)
937 for (i = n_digits; i; i--)
939 if (i % 3 == 0 && n_digits > i && n_items > n_reserved)
942 *dst++ = fp->type == FMT_COMMA ? set_grouping : set_decimal;
947 /* Copy decimal places and insert % if necessary. */
948 memcpy (dst, sp, fp->w - (sp - src));
949 if (fp->type == FMT_PCT && n_items > 0)
950 dst[fp->w - (sp - src)] = '%';
953 /* Returns 1 if YEAR (i.e., 1987) can be represented in four digits, 0
958 if (year >= 1 && year <= 9999)
960 msg (ME, _("Year %d cannot be represented in four digits for "
961 "output formatting purposes."), year);
966 try_CCx (char *dst, const struct fmt_spec *fp, double v)
968 struct set_cust_currency *cc = &set_cc[fp->type - FMT_CCA];
976 /* Determine length available, decimal character for number
978 f.type = cc->decimal == set_decimal ? FMT_COMMA : FMT_DOT;
979 f.w = fp->w - strlen (cc->prefix) - strlen (cc->suffix);
981 f.w -= strlen (cc->neg_prefix) + strlen (cc->neg_suffix) - 1;
983 /* Convert -0 to +0. */
990 /* There's room for all that currency crap. Let's do the F
992 if (!convert_F (buf, &f, (union value *) &v) || *buf == '*')
994 insert_commas (buf2, buf, &f);
996 /* Postprocess back into buf. */
999 cp = stpcpy (cp, cc->neg_prefix);
1000 cp = stpcpy (cp, cc->prefix);
1006 assert ((v >= 0) ^ (*bp == '-'));
1010 memcpy (cp, bp, f.w - (bp - buf2));
1011 cp += f.w - (bp - buf2);
1013 cp = stpcpy (cp, cc->suffix);
1015 cp = stpcpy (cp, cc->neg_suffix);
1017 /* Copy into dst. */
1018 assert (cp - buf <= fp->w);
1019 if (cp - buf < fp->w)
1021 memcpy (&dst[fp->w - (cp - buf)], buf, cp - buf);
1022 memset (dst, ' ', fp->w - (cp - buf));
1025 memcpy (dst, buf, fp->w);
1030 /* This routine relies on the underlying implementation of sprintf:
1032 If the number has a magnitude 1e40 or greater, then we needn't
1033 bother with it, since it's guaranteed to need processing in
1034 scientific notation.
1036 Otherwise, do a binary search for the base-10 magnitude of the
1037 thing. log10() is not accurate enough, and the alternatives are
1038 frightful. Besides, we never need as many as 6 (pairs of)
1039 comparisons. The algorithm used for searching is Knuth's Algorithm
1040 6.2.1C (Uniform binary search).
1042 DON'T CHANGE ANYTHING HERE UNLESS YOU'VE THOUGHT ABOUT IT FOR A
1043 LONG TIME! The rest of the program is heavily dependent on
1044 specific properties of this routine's output. LOG ALL CHANGES! */
1046 try_F (char *dst, const struct fmt_spec *fp, const union value *value)
1048 /* This is the DELTA array from Knuth.
1049 DELTA[j] = floor((40+2**(j-1))/(2**j)). */
1050 static const int delta[8] =
1052 0, (40 + 1) / 2, (40 + 2) / 4, (40 + 4) / 8, (40 + 8) / 16,
1053 (40 + 16) / 32, (40 + 32) / 64, (40 + 64) / 128,
1056 /* The number of digits in floor(v), including sign. This is `i'
1058 int n_int = (40 + 1) / 2;
1060 /* Used to step through delta[]. This is `j' from Knuth. */
1064 double v = value->f;
1066 /* Magnitude of v. This is `K' from Knuth. */
1069 /* Number of characters for the fractional part, including the
1073 /* Pointer into buf used for formatting. */
1076 /* Used to count characters formatted by nsprintf(). */
1079 /* Temporary buffer. */
1082 /* First check for infinities and NaNs. 12/13/96. */
1085 n = nsprintf (buf, "%f", v);
1087 memset (buf, '*', fp->w);
1090 memmove (&buf[fp->w - n], buf, n);
1091 memset (buf, ' ', fp->w - n);
1093 memcpy (dst, buf, fp->w);
1097 /* Then check for radically out-of-range values. */
1099 if (mag >= power10[fp->w])
1106 /* Avoid printing `-.000'. 7/6/96. */
1107 if (approx_eq (v, 0.0))
1111 /* Now perform a `uniform binary search' based on the tables
1112 power10[] and delta[]. After this step, nint is the number of
1113 digits in floor(v), including any sign. */
1116 if (mag >= power10[n_int]) /* Should this be approx_ge()? */
1119 n_int += delta[j++];
1121 else if (mag < power10[n_int - 1])
1124 n_int -= delta[j++];
1130 /* If we have any decimal places, then there is a decimal point,
1136 /* 1/10/96: If there aren't any digits at all, add one. This occurs
1137 only when fabs(v) < 1.0. */
1138 if (n_int + n_dec == 0)
1141 /* Give space for a minus sign. Moved 1/10/96. */
1145 /* Normally we only go through the loop once; occasionally twice.
1146 Three times or more indicates a very serious bug somewhere. */
1149 /* Check out the total length of the string. */
1151 if (n_int + n_dec > fp->w)
1153 /* The string is too long. Let's see what can be done. */
1155 /* If we can, just reduce the number of decimal places. */
1156 n_dec = fp->w - n_int;
1160 else if (n_int + n_dec < fp->w)
1162 /* The string is too short. Left-pad with spaces. */
1163 int n_spaces = fp->w - n_int - n_dec;
1164 memset (cp, ' ', n_spaces);
1168 /* Finally, format the number. */
1170 n = nsprintf (cp, "%.*f", n_dec - 1, v);
1172 n = nsprintf (cp, "%.0f", v);
1174 /* If v is positive and its magnitude is less than 1... */
1179 /* The value rounds to `.###'. */
1180 memmove (cp, &cp[1], n - 1);
1185 /* The value rounds to `1.###'. */
1190 /* Else if v is negative and its magnitude is less than 1... */
1191 else if (v < 0 && n_int == 1)
1195 /* The value rounds to `-.###'. */
1196 memmove (&cp[1], &cp[2], n - 2);
1201 /* The value rounds to `-1.###'. */
1207 /* Check for a correct number of digits & decimal places & stuff.
1208 This is just a desperation check. Hopefully it won't fail too
1209 often, because then we have to run through the whole loop again:
1210 sprintf() is not a fast operation with floating-points! */
1211 if (n == n_int + n_dec)
1213 /* Convert periods `.' to commas `,' for our foreign friends. */
1214 if ((set_decimal == ',' && fp->type != FMT_DOT)
1215 || (set_decimal == '.' && fp->type == FMT_DOT))
1217 cp = strchr (cp, '.');
1222 memcpy (dst, buf, fp->w);
1226 n_int = n - n_dec; /* FIXME? Need an idiot check on resulting n_int? */