35 |
#include "var.h" |
#include "var.h" |
36 |
|
|
37 |
#include "debug-print.h" |
#include "debug-print.h" |
|
|
|
|
/* In older versions, numbers got their trailing zeros stripped. |
|
|
Newer versions leave them on when there's room. Comment this next |
|
|
line out for retro styling. */ |
|
|
#define NEW_STYLE 1 |
|
38 |
|
|
39 |
/* Public functions. */ |
/* Public functions. */ |
40 |
|
|
43 |
static numeric_converter convert_Z, convert_IB, convert_P, convert_PIB; |
static numeric_converter convert_Z, convert_IB, convert_P, convert_PIB; |
44 |
static numeric_converter convert_PIBHEX, convert_PK, convert_RB; |
static numeric_converter convert_PIBHEX, convert_PK, convert_RB; |
45 |
static numeric_converter convert_RBHEX, convert_CCx, convert_date; |
static numeric_converter convert_RBHEX, convert_CCx, convert_date; |
46 |
static numeric_converter convert_time, convert_WKDAY, convert_MONTH, try_F; |
static numeric_converter convert_time, convert_WKDAY, convert_MONTH; |
47 |
|
|
48 |
|
static numeric_converter try_F, convert_infinite; |
49 |
|
|
50 |
typedef int string_converter (char *, const struct fmt_spec *, const char *); |
typedef int string_converter (char *, const struct fmt_spec *, const char *); |
51 |
static string_converter convert_A, convert_AHEX; |
static string_converter convert_A, convert_AHEX; |
193 |
void |
void |
194 |
num_to_string (double v, char *s, int w, int d) |
num_to_string (double v, char *s, int w, int d) |
195 |
{ |
{ |
|
/* Dummy to pass to convert_F. */ |
|
196 |
struct fmt_spec f; |
struct fmt_spec f; |
197 |
|
f.type = FMT_F; |
|
#if !NEW_STYLE |
|
|
/* Pointer to `.' in S. */ |
|
|
char *decp; |
|
|
|
|
|
/* Pointer to `E' in S. */ |
|
|
char *expp; |
|
|
|
|
|
/* Number of characters to delete. */ |
|
|
int n = 0; |
|
|
#endif |
|
|
|
|
198 |
f.w = w; |
f.w = w; |
199 |
f.d = d; |
f.d = d; |
200 |
|
convert_F (s, &f, v); |
|
/* Cut out the jokers. */ |
|
|
if (!finite (v)) |
|
|
{ |
|
|
char temp[9]; |
|
|
int len; |
|
|
|
|
|
if (isnan (v)) |
|
|
{ |
|
|
memcpy (temp, "NaN", 3); |
|
|
len = 3; |
|
|
} |
|
|
else if (isinf (v)) |
|
|
{ |
|
|
memcpy (temp, "+Infinity", 9); |
|
|
if (v < 0) |
|
|
temp[0] = '-'; |
|
|
len = 9; |
|
|
} |
|
|
else |
|
|
{ |
|
|
memcpy (temp, _("Unknown"), 7); |
|
|
len = 7; |
|
|
} |
|
|
if (w > len) |
|
|
{ |
|
|
int pad = w - len; |
|
|
memset (s, ' ', pad); |
|
|
s += pad; |
|
|
w -= pad; |
|
|
} |
|
|
memcpy (s, temp, w); |
|
|
return; |
|
|
} |
|
|
|
|
|
try_F (s, &f, v); |
|
|
|
|
|
#if !NEW_STYLE |
|
|
decp = memchr (s, set_decimal, w); |
|
|
if (!decp) |
|
|
return; |
|
|
|
|
|
/* If there's an `E' we can only delete 0s before the E. */ |
|
|
expp = memchr (s, 'E', w); |
|
|
if (expp) |
|
|
{ |
|
|
while (expp[-n - 1] == '0') |
|
|
n++; |
|
|
if (expp[-n - 1] == set_decimal) |
|
|
n++; |
|
|
memmove (&s[n], s, expp - s - n); |
|
|
memset (s, ' ', n); |
|
|
return; |
|
|
} |
|
|
|
|
|
/* Otherwise delete all trailing 0s. */ |
|
|
n++; |
|
|
while (s[w - n] == '0') |
|
|
n++; |
|
|
if (s[w - n] != set_decimal) |
|
|
{ |
|
|
/* Avoid stripping `.0' to `'. */ |
|
|
if (w == n || !isdigit ((unsigned char) s[w - n - 1])) |
|
|
n -= 2; |
|
|
} |
|
|
else |
|
|
n--; |
|
|
memmove (&s[n], s, w - n); |
|
|
memset (s, ' ', n); |
|
|
#endif |
|
201 |
} |
} |
202 |
|
|
203 |
/* Main conversion functions. */ |
/* Main conversion functions. */ |
211 |
#error Write your own floating-point output routines. |
#error Write your own floating-point output routines. |
212 |
#endif |
#endif |
213 |
|
|
|
/* PORTME: |
|
|
|
|
|
Some of the routines in this file are likely very specific to |
|
|
base-2 representation of floating-point numbers, most notably the |
|
|
routines that use frexp() or ldexp(). These attempt to extract |
|
|
individual digits by setting the base-2 exponent and |
|
|
multiplying/dividing by powers of 2. In base-2 numeration systems, |
|
|
this just nudges the exponent up or down, but in base-10 floating |
|
|
point, such multiplications/division can cause catastrophic loss of |
|
|
precision. |
|
|
|
|
|
The author has never personally used a machine that didn't use |
|
|
binary floating point formats, so he is unwilling, and perhaps |
|
|
unable, to code around this "problem". */ |
|
|
|
|
214 |
/* Converts a number between 0 and 15 inclusive to a `hexit' |
/* Converts a number between 0 and 15 inclusive to a `hexit' |
215 |
[0-9A-F]. */ |
[0-9A-F]. */ |
216 |
#define MAKE_HEXIT(X) ("0123456789ABCDEF"[X]) |
#define MAKE_HEXIT(X) ("0123456789ABCDEF"[X]) |
270 |
/* Ranged number of decimal places. */ |
/* Ranged number of decimal places. */ |
271 |
int d; |
int d; |
272 |
|
|
273 |
/* Check that the format is width enough. |
if (!finite (number)) |
274 |
|
return convert_infinite (dst, fp, number); |
275 |
|
|
276 |
|
/* Check that the format is wide enough. |
277 |
Although PSPP generally checks this, convert_E() can be called as |
Although PSPP generally checks this, convert_E() can be called as |
278 |
a fallback from other formats which do not check. */ |
a fallback from other formats which do not check. */ |
279 |
if (fp->w < 6) |
if (fp->w < 6) |
465 |
} |
} |
466 |
memcpy (dst, temp, fp->w); |
memcpy (dst, temp, fp->w); |
467 |
#ifndef WORDS_BIGENDIAN |
#ifndef WORDS_BIGENDIAN |
468 |
mm_reverse (dst, fp->w); |
buf_reverse (dst, fp->w); |
469 |
#endif |
#endif |
470 |
|
|
471 |
return 1; |
return 1; |
529 |
((unsigned char *) dst)[i] = floor (frac); |
((unsigned char *) dst)[i] = floor (frac); |
530 |
} |
} |
531 |
#ifndef WORDS_BIGENDIAN |
#ifndef WORDS_BIGENDIAN |
532 |
mm_reverse (dst, fp->w); |
buf_reverse (dst, fp->w); |
533 |
#endif |
#endif |
534 |
|
|
535 |
return 1; |
return 1; |
756 |
|
|
757 |
if (buf[0] == 0) |
if (buf[0] == 0) |
758 |
return 0; |
return 0; |
759 |
st_bare_pad_copy (dst, buf, fp->w); |
buf_copy_str_rpad (dst, fp->w, buf); |
760 |
return 1; |
return 1; |
761 |
} |
} |
762 |
|
|
806 |
|
|
807 |
cp = spprintf (cp, ":%0*.*f", w, d, fmod (time, 60.)); |
cp = spprintf (cp, ":%0*.*f", w, d, fmod (time, 60.)); |
808 |
} |
} |
809 |
st_bare_pad_copy (dst, temp_buf, fp->w); |
buf_copy_str_rpad (dst, fp->w, temp_buf); |
810 |
|
|
811 |
return 1; |
return 1; |
812 |
} |
} |
826 |
(double) wkday); |
(double) wkday); |
827 |
return 0; |
return 0; |
828 |
} |
} |
829 |
st_bare_pad_copy (dst, weekdays[(int) wkday - 1], fp->w); |
buf_copy_str_rpad (dst, fp->w, weekdays[(int) wkday - 1]); |
830 |
|
|
831 |
return 1; |
return 1; |
832 |
} |
} |
847 |
return 0; |
return 0; |
848 |
} |
} |
849 |
|
|
850 |
st_bare_pad_copy (dst, months[(int) month - 1], fp->w); |
buf_copy_str_rpad (dst, fp->w, months[(int) month - 1]); |
851 |
|
|
852 |
return 1; |
return 1; |
853 |
} |
} |
1025 |
return 1; |
return 1; |
1026 |
} |
} |
1027 |
|
|
1028 |
/* This routine relies on the underlying implementation of sprintf: |
static int |
1029 |
|
format_and_round (char *dst, double number, const struct fmt_spec *fp, |
1030 |
|
int decimals); |
1031 |
|
|
1032 |
If the number has a magnitude 1e40 or greater, then we needn't |
/* Tries to format NUMBER into DST as the F format specified in |
1033 |
bother with it, since it's guaranteed to need processing in |
*FP. Return true if successful, false on failure. */ |
|
scientific notation. |
|
|
|
|
|
Otherwise, do a binary search for the base-10 magnitude of the |
|
|
thing. log10() is not accurate enough, and the alternatives are |
|
|
frightful. Besides, we never need as many as 6 (pairs of) |
|
|
comparisons. The algorithm used for searching is Knuth's Algorithm |
|
|
6.2.1C (Uniform binary search). |
|
|
|
|
|
DON'T CHANGE ANYTHING HERE UNLESS YOU'VE THOUGHT ABOUT IT FOR A |
|
|
LONG TIME! The rest of the program is heavily dependent on |
|
|
specific properties of this routine's output. LOG ALL CHANGES! */ |
|
1034 |
static int |
static int |
1035 |
try_F (char *dst, const struct fmt_spec *fp, double number) |
try_F (char *dst, const struct fmt_spec *fp, double number) |
1036 |
{ |
{ |
1037 |
/* This is the DELTA array from Knuth. |
assert (fp->w <= 40); |
1038 |
DELTA[j] = floor((40+2**(j-1))/(2**j)). */ |
if (finite (number)) |
1039 |
static const int delta[8] = |
{ |
1040 |
{ |
if (fabs (number) < power10[fp->w]) |
1041 |
0, (40 + 1) / 2, (40 + 2) / 4, (40 + 4) / 8, (40 + 8) / 16, |
{ |
1042 |
(40 + 16) / 32, (40 + 32) / 64, (40 + 64) / 128, |
/* The value may fit in the field. */ |
1043 |
}; |
if (fp->d == 0) |
1044 |
|
{ |
1045 |
|
/* There are no decimal places, so there's no way |
1046 |
|
that the value can be shortened. Either it fits |
1047 |
|
or it doesn't. */ |
1048 |
|
char buf[40]; |
1049 |
|
sprintf (buf, "%*.0f", fp->w, number); |
1050 |
|
if (strlen (buf) <= fp->w) |
1051 |
|
{ |
1052 |
|
buf_copy_str_lpad (dst, fp->w, buf); |
1053 |
|
return true; |
1054 |
|
} |
1055 |
|
else |
1056 |
|
return false; |
1057 |
|
} |
1058 |
|
else |
1059 |
|
{ |
1060 |
|
/* First try to format it with 2 extra decimal |
1061 |
|
places. This gives us a good chance of not |
1062 |
|
needing even more decimal places, but it also |
1063 |
|
avoids wasting too much time formatting more |
1064 |
|
decimal places on the first try. */ |
1065 |
|
int result = format_and_round (dst, number, fp, fp->d + 2); |
1066 |
|
if (result >= 0) |
1067 |
|
return result; |
1068 |
|
|
1069 |
|
/* 2 extra decimal places weren't enough to |
1070 |
|
correctly round. Try again with the maximum |
1071 |
|
number of places. */ |
1072 |
|
return format_and_round (dst, number, fp, LDBL_DIG + 1); |
1073 |
|
} |
1074 |
|
} |
1075 |
|
else |
1076 |
|
{ |
1077 |
|
/* The value is too big to fit in the field. */ |
1078 |
|
return false; |
1079 |
|
} |
1080 |
|
} |
1081 |
|
else |
1082 |
|
return convert_infinite (dst, fp, number); |
1083 |
|
} |
1084 |
|
|
1085 |
/* The number of digits in floor(number), including sign. This |
/* Tries to compose NUMBER into DST in format FP by first |
1086 |
is `i' from Knuth. */ |
formatting it with DECIMALS decimal places, then rounding off |
1087 |
int n_int = (40 + 1) / 2; |
to as many decimal places will fit or the number specified in |
1088 |
|
FP, whichever is fewer. |
1089 |
|
|
1090 |
/* Used to step through delta[]. This is `j' from Knuth. */ |
Returns 1 if conversion succeeds, 0 if this try at conversion |
1091 |
int j = 2; |
failed and so will any other tries (because the integer part |
1092 |
|
of the number is too long), or -1 if this try failed but |
1093 |
|
another with higher DECIMALS might succeed (because we'd be |
1094 |
|
able to properly round). */ |
1095 |
|
static int |
1096 |
|
format_and_round (char *dst, double number, const struct fmt_spec *fp, |
1097 |
|
int decimals) |
1098 |
|
{ |
1099 |
|
/* Number of characters before the decimal point, |
1100 |
|
which includes digits and possibly a minus sign. */ |
1101 |
|
int predot_chars; |
1102 |
|
|
1103 |
/* Magnitude of number. This is `K' from Knuth. */ |
/* Number of digits in the output fraction, |
1104 |
double mag; |
which may be smaller than fp->d if there's not enough room. */ |
1105 |
|
int fraction_digits; |
1106 |
|
|
1107 |
/* Number of characters for the fractional part, including the |
/* Points to last digit that will remain in the fraction after |
1108 |
decimal point. */ |
rounding. */ |
1109 |
int n_dec; |
char *final_frac_dig; |
1110 |
|
|
1111 |
/* Pointer into buf used for formatting. */ |
/* Round up? */ |
1112 |
char *cp; |
bool round_up; |
1113 |
|
|
1114 |
|
char buf[128]; |
1115 |
|
|
1116 |
|
assert (decimals > fp->d); |
1117 |
|
if (decimals > LDBL_DIG) |
1118 |
|
decimals = LDBL_DIG + 1; |
1119 |
|
|
1120 |
/* Used to count characters formatted by nsprintf(). */ |
sprintf (buf, "%.*f", decimals, number); |
|
int n; |
|
1121 |
|
|
1122 |
/* Temporary buffer. */ |
if (!memcmp (buf, "0.", 2)) |
1123 |
char buf[128]; |
memmove (buf, buf + 1, strlen (buf)); |
1124 |
|
else if (!memcmp (buf, "-0.", 3)) |
1125 |
|
memmove (buf + 1, buf + 2, strlen (buf + 1)); |
1126 |
|
|
1127 |
/* First check for infinities and NaNs. 12/13/96. */ |
predot_chars = strcspn (buf, "."); |
1128 |
if (!finite (number)) |
if (predot_chars > fp->w) |
1129 |
{ |
{ |
1130 |
n = nsprintf (buf, "%f", number); |
/* Can't possibly fit. */ |
1131 |
if (n > fp->w) |
return 0; |
1132 |
memset (buf, '*', fp->w); |
} |
1133 |
else if (n < fp->w) |
else if (predot_chars == fp->w) |
1134 |
{ |
{ |
1135 |
memmove (&buf[fp->w - n], buf, n); |
/* Exact fit for integer part and sign. */ |
|
memset (buf, ' ', fp->w - n); |
|
|
} |
|
1136 |
memcpy (dst, buf, fp->w); |
memcpy (dst, buf, fp->w); |
1137 |
return 1; |
return 1; |
1138 |
} |
} |
1139 |
|
else if (predot_chars + 1 == fp->w) |
|
/* Then check for radically out-of-range values. */ |
|
|
mag = fabs (number); |
|
|
if (mag >= power10[fp->w]) |
|
|
return 0; |
|
|
|
|
|
if (mag < 1.0) |
|
1140 |
{ |
{ |
1141 |
n_int = 0; |
/* There's room for the decimal point, but not for any |
1142 |
|
digits of the fraction. |
1143 |
|
Right-justify the integer part and sign. */ |
1144 |
|
dst[0] = ' '; |
1145 |
|
memcpy (dst + 1, buf, fp->w); |
1146 |
|
return 1; |
1147 |
|
} |
1148 |
|
|
1149 |
/* Avoid printing `-.000'. 7/6/96. */ |
/* It looks like we have room for at least one digit of the |
1150 |
if (mag < EPSILON) |
fraction. Figure out how many. */ |
1151 |
number = 0.0; |
fraction_digits = fp->w - predot_chars - 1; |
1152 |
|
if (fraction_digits > fp->d) |
1153 |
|
fraction_digits = fp->d; |
1154 |
|
final_frac_dig = buf + predot_chars + fraction_digits; |
1155 |
|
|
1156 |
|
/* Decide rounding direction and truncate string. */ |
1157 |
|
if (final_frac_dig[1] == '5' |
1158 |
|
&& strspn (final_frac_dig + 2, "0") == strlen (final_frac_dig + 2)) |
1159 |
|
{ |
1160 |
|
/* Exactly 1/2. */ |
1161 |
|
if (decimals <= LDBL_DIG) |
1162 |
|
{ |
1163 |
|
/* Don't have enough fractional digits to know which way to |
1164 |
|
round. We can format with more decimal places, so go |
1165 |
|
around again. */ |
1166 |
|
return -1; |
1167 |
|
} |
1168 |
|
else |
1169 |
|
{ |
1170 |
|
/* We used up all our fractional digits and still don't |
1171 |
|
know. Round to even. */ |
1172 |
|
round_up = (final_frac_dig[0] - '0') % 2 != 0; |
1173 |
|
} |
1174 |
} |
} |
1175 |
else |
else |
1176 |
/* Now perform a `uniform binary search' based on the tables |
round_up = final_frac_dig[1] >= '5'; |
1177 |
power10[] and delta[]. After this step, nint is the number of |
final_frac_dig[1] = '\0'; |
|
digits in floor(number), including any sign. */ |
|
|
for (;;) |
|
|
{ |
|
|
if (mag >= power10[n_int]) |
|
|
{ |
|
|
assert (delta[j]); |
|
|
n_int += delta[j++]; |
|
|
} |
|
|
else if (mag < power10[n_int - 1]) |
|
|
{ |
|
|
assert (delta[j]); |
|
|
n_int -= delta[j++]; |
|
|
} |
|
|
else |
|
|
break; |
|
|
} |
|
1178 |
|
|
1179 |
/* If we have any decimal places, then there is a decimal point, |
/* Do rounding. */ |
1180 |
too. */ |
if (round_up) |
1181 |
n_dec = fp->d; |
{ |
1182 |
if (n_dec) |
char *cp = final_frac_dig; |
1183 |
n_dec++; |
for (;;) |
1184 |
|
{ |
1185 |
/* 1/10/96: If there aren't any digits at all, add one. This occurs |
if (*cp >= '0' && *cp <= '8') |
1186 |
only when fabs(number) < 1.0. */ |
{ |
1187 |
if (n_int + n_dec == 0) |
(*cp)++; |
1188 |
n_int++; |
break; |
1189 |
|
} |
1190 |
|
else if (*cp == '9') |
1191 |
|
*cp = '0'; |
1192 |
|
else |
1193 |
|
assert (*cp == '.'); |
1194 |
|
|
1195 |
|
if (cp == buf || *--cp == '-') |
1196 |
|
{ |
1197 |
|
size_t length; |
1198 |
|
|
1199 |
|
/* Tried to go past the leftmost digit. Insert a 1. */ |
1200 |
|
memmove (cp + 1, cp, strlen (cp) + 1); |
1201 |
|
*cp = '1'; |
1202 |
|
|
1203 |
|
length = strlen (buf); |
1204 |
|
if (length > fp->w) |
1205 |
|
{ |
1206 |
|
/* Inserting the `1' overflowed our space. |
1207 |
|
Drop a decimal place. */ |
1208 |
|
buf[--length] = '\0'; |
1209 |
|
|
1210 |
|
/* If that was the last decimal place, drop the |
1211 |
|
decimal point too. */ |
1212 |
|
if (buf[length - 1] == '.') |
1213 |
|
buf[length - 1] = '\0'; |
1214 |
|
} |
1215 |
|
|
1216 |
|
break; |
1217 |
|
} |
1218 |
|
} |
1219 |
|
} |
1220 |
|
|
1221 |
/* Give space for a minus sign. Moved 1/10/96. */ |
buf_copy_str_lpad (dst, fp->w, buf); |
1222 |
if (number < 0) |
return 1; |
1223 |
n_int++; |
} |
1224 |
|
|
1225 |
/* Normally we only go through the loop once; occasionally twice. |
/* Formats non-finite NUMBER into DST according to the width |
1226 |
Three times or more indicates a very serious bug somewhere. */ |
given in FP. */ |
1227 |
for (;;) |
static int |
1228 |
{ |
convert_infinite (char *dst, const struct fmt_spec *fp, double number) |
1229 |
/* Check out the total length of the string. */ |
{ |
1230 |
cp = buf; |
assert (!finite (number)); |
1231 |
if (n_int + n_dec > fp->w) |
|
1232 |
{ |
if (fp->w >= 3) |
1233 |
/* The string is too long. Let's see what can be done. */ |
{ |
1234 |
if (n_int <= fp->w) |
const char *s; |
|
/* If we can, just reduce the number of decimal places. */ |
|
|
n_dec = fp->w - n_int; |
|
|
else |
|
|
return 0; |
|
|
} |
|
|
else if (n_int + n_dec < fp->w) |
|
|
{ |
|
|
/* The string is too short. Left-pad with spaces. */ |
|
|
int n_spaces = fp->w - n_int - n_dec; |
|
|
memset (cp, ' ', n_spaces); |
|
|
cp += n_spaces; |
|
|
} |
|
1235 |
|
|
1236 |
/* Finally, format the number. */ |
if (isnan (number)) |
1237 |
if (n_dec) |
s = "NaN"; |
1238 |
n = nsprintf (cp, "%.*f", n_dec - 1, number); |
else if (isinf (number)) |
1239 |
|
s = number > 0 ? "+Infinity" : "-Infinity"; |
1240 |
else |
else |
1241 |
n = nsprintf (cp, "%.0f", number); |
s = "Unknown"; |
1242 |
|
|
1243 |
/* If number is positive and its magnitude is less than |
buf_copy_str_lpad (dst, fp->w, s); |
|
1... */ |
|
|
if (n_int == 0) |
|
|
{ |
|
|
if (*cp == '0') |
|
|
{ |
|
|
/* The value rounds to `.###'. */ |
|
|
memmove (cp, &cp[1], n - 1); |
|
|
n--; |
|
|
} |
|
|
else |
|
|
{ |
|
|
/* The value rounds to `1.###'. */ |
|
|
n_int = 1; |
|
|
continue; |
|
|
} |
|
|
} |
|
|
/* Else if number is negative and its magnitude is less |
|
|
than 1... */ |
|
|
else if (number < 0 && n_int == 1) |
|
|
{ |
|
|
if (cp[1] == '0') |
|
|
{ |
|
|
/* The value rounds to `-.###'. */ |
|
|
memmove (&cp[1], &cp[2], n - 2); |
|
|
n--; |
|
|
} |
|
|
else |
|
|
{ |
|
|
/* The value rounds to `-1.###'. */ |
|
|
n_int = 2; |
|
|
continue; |
|
|
} |
|
|
} |
|
|
|
|
|
/* Check for a correct number of digits & decimal places & stuff. |
|
|
This is just a desperation check. Hopefully it won't fail too |
|
|
often, because then we have to run through the whole loop again: |
|
|
sprintf() is not a fast operation with floating-points! */ |
|
|
if (n == n_int + n_dec) |
|
|
{ |
|
|
/* Convert periods `.' to commas `,' for our foreign friends. */ |
|
|
if ((get_decimal() == ',' && fp->type != FMT_DOT) |
|
|
|| (get_decimal() == '.' && fp->type == FMT_DOT)) |
|
|
{ |
|
|
cp = strchr (cp, '.'); |
|
|
if (cp) |
|
|
*cp = ','; |
|
|
} |
|
|
|
|
|
memcpy (dst, buf, fp->w); |
|
|
return 1; |
|
|
} |
|
|
|
|
|
n_int = n - n_dec; /* FIXME? Need an idiot check on resulting n_int? */ |
|
1244 |
} |
} |
1245 |
|
else |
1246 |
|
memset (dst, '*', fp->w); |
1247 |
|
|
1248 |
|
return true; |
1249 |
} |
} |