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., 51 Franklin Street, Fifth Floor, Boston, MA
41 #define _(msgid) gettext (msgid)
43 #include "debug-print.h"
45 /* Specialized error routine. */
47 static void dls_error (const struct data_in *, const char *format, ...)
51 vdls_error (const struct data_in *i, const char *format, va_list args)
56 if (i->flags & DI_IGNORE_ERROR)
60 if (!getl_reading_script)
61 ds_puts (&title, _("data-file error: "));
63 ds_printf (&title, _("(column %d"), i->f1);
65 ds_printf (&title, _("(columns %d-%d"), i->f1, i->f2);
66 ds_printf (&title, _(", field type %s) "), fmt_to_string (&i->format));
69 err_location (&e.where);
70 e.title = ds_c_str (&title);
72 err_vmsg (&e, format, args);
78 dls_error (const struct data_in *i, const char *format, ...)
82 va_start (args, format);
83 vdls_error (i, format, args);
87 /* Parsing utility functions. */
89 /* Excludes leading and trailing whitespace from I by adjusting
92 trim_whitespace (struct data_in *i)
94 while (i->s < i->e && isspace (i->s[0]))
97 while (i->s < i->e && isspace (i->e[-1]))
101 /* Returns nonzero if we're not at the end of the string being
104 have_char (struct data_in *i)
109 /* If implied decimal places are enabled, apply them to
112 apply_implied_decimals (struct data_in *i)
114 if ((i->flags & DI_IMPLIED_DECIMALS) && i->format.d > 0)
115 i->v->f /= pow (10., i->format.d);
118 /* Format parsers. */
120 static bool parse_int (struct data_in *i, long *result);
122 /* This function is based on strtod() from the GNU C library. */
124 parse_numeric (struct data_in *i)
126 int sign; /* +1 or -1. */
127 double num; /* The number so far. */
129 bool got_dot; /* Found a decimal point. */
130 size_t digit_cnt; /* Count of digits. */
132 int decimal; /* Decimal point character. */
133 int grouping; /* Grouping character. */
135 long int exponent; /* Number's exponent. */
136 int type; /* Usually same as i->format.type. */
140 type = i->format.type;
141 if (type == FMT_DOLLAR && have_char (i) && *i->s == '$')
150 sign = *i->s == '-' ? -1 : 1;
151 if (*i->s == '-' || *i->s == '+')
159 decimal = get_decimal();
160 grouping = get_grouping();
164 decimal = get_grouping();
165 grouping = get_decimal();
173 for (; have_char (i); i->s++)
179 /* Make sure that multiplication by 10 will not overflow. */
180 if (num > DBL_MAX * 0.1)
181 /* The value of the digit doesn't matter, since we have already
182 gotten as many digits as can be represented in a `double'.
183 This doesn't necessarily mean the result will overflow.
184 The exponent may reduce it to within range.
186 We just need to record that there was another
187 digit so that we can multiply by 10 later. */
190 num = (num * 10.0) + (*i->s - '0');
192 /* Keep track of the number of digits after the decimal point.
193 If we just divided by 10 here, we would lose precision. */
197 else if (!got_dot && *i->s == decimal)
198 /* Record that we have found the decimal point. */
200 else if ((type != FMT_COMMA && type != FMT_DOT) || *i->s != grouping)
201 /* Any other character terminates the number. */
212 dls_error (i, _("Field does not form a valid floating-point constant."));
217 if (have_char (i) && strchr ("eEdD-+", *i->s))
219 /* Get the exponent specified after the `e' or `E'. */
224 if (!parse_int (i, &exp))
232 else if (!got_dot && (i->flags & DI_IMPLIED_DECIMALS))
233 exponent -= i->format.d;
235 if (type == FMT_PCT && have_char (i) && *i->s == '%')
239 dls_error (i, _("Field contents followed by garbage."));
250 /* Multiply NUM by 10 to the EXPONENT power, checking for overflow
254 if (-exponent + digit_cnt > -(DBL_MIN_10_EXP) + 5
255 || num < DBL_MIN * pow (10.0, (double) -exponent))
257 dls_error (i, _("Underflow in floating-point constant."));
262 num *= pow (10.0, (double) exponent);
264 else if (exponent > 0)
266 if (num > DBL_MAX * pow (10.0, (double) -exponent))
268 dls_error (i, _("Overflow in floating-point constant."));
273 num *= pow (10.0, (double) exponent);
276 i->v->f = sign > 0 ? num : -num;
280 /* Returns the integer value of hex digit C. */
284 const char s[] = "0123456789abcdef";
285 const char *cp = strchr (s, tolower ((unsigned char) c));
292 parse_N (struct data_in *i)
294 const unsigned char *cp;
297 for (cp = i->s; cp < i->e; cp++)
301 dls_error (i, _("All characters in field must be digits."));
305 i->v->f = i->v->f * 10.0 + *cp - '0';
308 apply_implied_decimals (i);
313 parse_PIBHEX (struct data_in *i)
316 const unsigned char *cp;
321 for (cp = i->s; cp < i->e; cp++)
325 dls_error (i, _("Unrecognized character in field."));
329 n = n * 16.0 + hexit_value (*cp);
337 parse_RBHEX (struct data_in *i)
339 /* Validate input. */
341 if ((i->e - i->s) % 2)
343 dls_error (i, _("Field must have even length."));
348 const unsigned char *cp;
350 for (cp = i->s; cp < i->e; cp++)
353 dls_error (i, _("Field must contain only hex digits."));
363 unsigned char c[sizeof (double)];
369 memset (u.c, 0, sizeof u.c);
370 for (j = 0; j < min ((i->e - i->s) / 2, sizeof u.d); j++)
371 u.c[j] = 16 * hexit_value (i->s[j * 2]) + hexit_value (i->s[j * 2 + 1]);
380 parse_Z (struct data_in *i)
383 bool got_dot = false;
385 /* Warn user that we suck. */
392 _("Quality of zoned decimal (Z) input format code is "
393 "suspect. Check your results three times. Report bugs "
394 "to %s."),PACKAGE_BUGREPORT);
399 /* Validate input. */
404 dls_error (i, _("Zoned decimal field contains fewer than 2 "
409 /* Copy sign into buf[0]. */
410 if ((i->e[-1] & 0xc0) != 0xc0)
412 dls_error (i, _("Bad sign byte in zoned decimal number."));
415 buf[0] = (i->e[-1] ^ (i->e[-1] >> 1)) & 0x10 ? '-' : '+';
417 /* Copy digits into buf[1 ... len - 1] and terminate string. */
419 const unsigned char *sp;
422 for (sp = i->s, dp = buf + 1; sp < i->e - 1; sp++, dp++)
428 else if ((*sp & 0xf0) == 0xf0 && (*sp & 0xf) < 10)
429 *dp = (*sp & 0xf) + '0';
432 dls_error (i, _("Format error in zoned decimal number."));
439 /* Parse as number. */
443 i->v->f = strtod ((char *) buf, (char **) &tail);
444 if ((unsigned char *) tail != i->e)
446 dls_error (i, _("Error in syntax of zoned decimal number."));
452 apply_implied_decimals (i);
458 parse_IB (struct data_in *i)
460 #ifndef WORDS_BIGENDIAN
467 /* We want the data to be in big-endian format. If this is a
468 little-endian machine, reverse the byte order. */
469 #ifdef WORDS_BIGENDIAN
472 memcpy (buf, i->s, i->e - i->s);
473 buf_reverse (buf, i->e - i->s);
477 /* If the value is negative, we need to logical-NOT each value
488 for (j = 0; j < i->e - i->s; j++)
489 i->v->f = i->v->f * 256.0 + (p[j] ^ xor);
492 /* If the value is negative, add 1 and set the sign, to complete a
493 two's-complement negation. */
495 i->v->f = -(i->v->f + 1.0);
497 apply_implied_decimals (i);
503 parse_PIB (struct data_in *i)
509 for (j = 0; j < i->e - i->s; j++)
510 i->v->f = i->v->f * 256.0 + i->s[j];
512 for (j = i->e - i->s - 1; j >= 0; j--)
513 i->v->f = i->v->f * 256.0 + i->s[j];
516 apply_implied_decimals (i);
522 parse_P (struct data_in *i)
524 const unsigned char *cp;
527 for (cp = i->s; cp < i->e - 1; cp++)
529 i->v->f = i->v->f * 10 + (*cp >> 4);
530 i->v->f = i->v->f * 10 + (*cp & 15);
532 i->v->f = i->v->f * 10 + (*cp >> 4);
533 if ((*cp ^ (*cp >> 1)) & 0x10)
536 apply_implied_decimals (i);
542 parse_PK (struct data_in *i)
544 const unsigned char *cp;
547 for (cp = i->s; cp < i->e; cp++)
549 i->v->f = i->v->f * 10 + (*cp >> 4);
550 i->v->f = i->v->f * 10 + (*cp & 15);
553 apply_implied_decimals (i);
559 parse_RB (struct data_in *i)
564 unsigned char c[sizeof (double)];
568 memset (u.c, 0, sizeof u.c);
569 memcpy (u.c, i->s, min ((int) sizeof (u.c), i->e - i->s));
576 parse_A (struct data_in *i)
578 ptrdiff_t len = i->e - i->s;
580 if (len >= i->format.w)
581 memcpy (i->v->s, i->s, i->format.w);
584 memcpy (i->v->s, i->s, len);
585 memset (i->v->s + len, ' ', i->format.w - len);
592 parse_AHEX (struct data_in *i)
594 /* Validate input. */
596 if ((i->e - i->s) % 2)
598 dls_error (i, _("Field must have even length."));
603 const unsigned char *cp;
605 for (cp = i->s; cp < i->e; cp++)
608 dls_error (i, _("Field must contain only hex digits."));
617 for (j = 0; j < min (i->e - i->s, i->format.w); j += 2)
618 i->v->s[j / 2] = hexit_value (i->s[j]) * 16 + hexit_value (i->s[j + 1]);
619 memset (i->v->s + (i->e - i->s) / 2, ' ', (i->format.w - (i->e - i->s)) / 2);
625 /* Date & time format components. */
627 /* Advances *CP past any whitespace characters. */
629 skip_whitespace (struct data_in *i)
631 while (isspace ((unsigned char) *i->s))
636 parse_leader (struct data_in *i)
643 force_have_char (struct data_in *i)
648 dls_error (i, _("Unexpected end of field."));
653 parse_int (struct data_in *i, long *result)
655 bool negative = false;
657 if (!force_have_char (i))
665 else if (*i->s == '-')
672 if (!isdigit (*i->s))
674 dls_error (i, _("Digit expected in field."));
681 *result = *result * 10 + *i->s++ - '0';
682 if (!have_char (i) || !isdigit (*i->s))
692 parse_day (struct data_in *i, long *day)
694 if (!parse_int (i, day))
696 if (*day >= 1 && *day <= 31)
699 dls_error (i, _("Day (%ld) must be between 1 and 31."), *day);
704 parse_day_count (struct data_in *i, long *day_count)
706 return parse_int (i, day_count);
710 parse_date_delimiter (struct data_in *i)
715 && (*i->s == '-' || *i->s == '/' || isspace (*i->s)
716 || *i->s == '.' || *i->s == ','))
724 dls_error (i, _("Delimiter expected between fields in date."));
728 /* Association between a name and a value. */
731 const char *name; /* Name. */
732 bool can_abbreviate; /* True if name may be abbreviated. */
733 int value; /* Value associated with name. */
736 /* Reads a name from I and sets *OUTPUT to the value associated
737 with that name. Returns true if successful, false otherwise. */
739 parse_enum (struct data_in *i, const char *what,
740 const struct enum_name *enum_names,
745 const struct enum_name *ep;
747 /* Consume alphabetic characters. */
750 while (have_char (i) && isalpha (*i->s))
757 dls_error (i, _("Parse error at `%c' expecting %s."), *i->s, what);
761 for (ep = enum_names; ep->name != NULL; ep++)
762 if ((ep->can_abbreviate
763 && lex_id_match_len (ep->name, strlen (ep->name), name, length))
764 || (!ep->can_abbreviate && length == strlen (ep->name)
765 && !buf_compare_case (name, ep->name, length)))
771 dls_error (i, _("Unknown %s `%.*s'."), what, (int) length, name);
776 parse_month (struct data_in *i, long *month)
778 static const struct enum_name month_names[] =
780 {"january", true, 1},
781 {"february", true, 2},
788 {"september", true, 9},
789 {"october", true, 10},
790 {"november", true, 11},
791 {"december", true, 12},
811 if (!force_have_char (i))
816 if (!parse_int (i, month))
818 if (*month >= 1 && *month <= 12)
821 dls_error (i, _("Month (%ld) must be between 1 and 12."), *month);
825 return parse_enum (i, _("month"), month_names, month);
829 parse_year (struct data_in *i, long *year)
831 if (!parse_int (i, year))
834 if (*year >= 0 && *year <= 199)
836 if (*year >= 1582 || *year <= 19999)
839 dls_error (i, _("Year (%ld) must be between 1582 and 19999."), *year);
844 parse_trailer (struct data_in *i)
850 dls_error (i, _("Trailing garbage \"%s\" following date."), i->s);
855 parse_julian (struct data_in *i, long *julian)
857 if (!parse_int (i, julian))
861 int day = *julian % 1000;
863 if (day < 1 || day > 366)
865 dls_error (i, _("Julian day (%d) must be between 1 and 366."), day);
871 int year = *julian / 1000;
873 if (year >= 0 && year <= 199)
875 else if (year < 1582 || year > 19999)
877 dls_error (i, _("Year (%d) must be between 1582 and 19999."), year);
886 parse_quarter (struct data_in *i, long *quarter)
888 if (!parse_int (i, quarter))
890 if (*quarter >= 1 && *quarter <= 4)
893 dls_error (i, _("Quarter (%ld) must be between 1 and 4."), *quarter);
898 parse_q_delimiter (struct data_in *i)
901 if (!have_char (i) || tolower (*i->s) != 'q')
903 dls_error (i, _("`Q' expected between quarter and year."));
912 parse_week (struct data_in *i, long *week)
914 if (!parse_int (i, week))
916 if (*week >= 1 && *week <= 53)
919 dls_error (i, _("Week (%ld) must be between 1 and 53."), *week);
924 parse_wk_delimiter (struct data_in *i)
928 || tolower (i->s[0]) != 'w' || tolower (i->s[1]) != 'k')
930 dls_error (i, _("`WK' expected between week and year."));
939 parse_time_delimiter (struct data_in *i)
943 while (have_char (i) && (*i->s == ':' || *i->s == '.' || isspace (*i->s)))
952 dls_error (i, _("Delimiter expected between fields in time."));
957 parse_hour (struct data_in *i, long *hour)
959 if (!parse_int (i, hour))
964 dls_error (i, _("Hour (%ld) must be positive."), *hour);
969 parse_minute (struct data_in *i, long *minute)
971 if (!parse_int (i, minute))
973 if (*minute >= 0 && *minute <= 59)
976 dls_error (i, _("Minute (%ld) must be between 0 and 59."), *minute);
981 parse_opt_second (struct data_in *i, double *second)
989 && (*i->s == ':' || *i->s == '.' || isspace (*i->s)))
995 if (!delim || !isdigit (*i->s))
1002 while (have_char (i) && isdigit (*i->s))
1004 if (have_char (i) && *i->s == '.')
1006 while (have_char (i) && isdigit (*i->s))
1010 *second = strtod (buf, NULL);
1016 parse_hour24 (struct data_in *i, long *hour24)
1018 if (!parse_int (i, hour24))
1020 if (*hour24 >= 0 && *hour24 <= 23)
1023 dls_error (i, _("Hour (%ld) must be between 0 and 23."), *hour24);
1029 parse_weekday (struct data_in *i, long *weekday)
1031 static const struct enum_name weekday_names[] =
1033 {"sunday", true, 1},
1035 {"monday", true, 2},
1037 {"tuesday", true, 3},
1039 {"wednesday", true, 4},
1041 {"thursday", true, 5},
1043 {"friday", true, 6},
1045 {"saturday", true, 7},
1051 return parse_enum (i, _("weekday"), weekday_names, weekday);
1055 parse_spaces (struct data_in *i)
1057 skip_whitespace (i);
1062 parse_sign (struct data_in *i, int *sign)
1064 if (!force_have_char (i))
1086 /* Date & time formats. */
1089 calendar_error (void *i_, const char *format, ...)
1091 struct data_in *i = i_;
1094 va_start (args, format);
1095 vdls_error (i, format, args);
1100 ymd_to_ofs (struct data_in *i, int year, int month, int day, double *ofs)
1102 *ofs = calendar_gregorian_to_offset (year, month, day, calendar_error, i);
1103 return *ofs != SYSMIS;
1107 ymd_to_date (struct data_in *i, int year, int month, int day, double *date)
1109 if (ymd_to_ofs (i, year, month, day, date))
1111 *date *= 60. * 60. * 24.;
1119 parse_DATE (struct data_in *i)
1121 long day, month, year;
1123 return (parse_leader (i)
1124 && parse_day (i, &day)
1125 && parse_date_delimiter (i)
1126 && parse_month (i, &month)
1127 && parse_date_delimiter (i)
1128 && parse_year (i, &year)
1129 && parse_trailer (i)
1130 && ymd_to_date (i, year, month, day, &i->v->f));
1134 parse_ADATE (struct data_in *i)
1136 long month, day, year;
1138 return (parse_leader (i)
1139 && parse_month (i, &month)
1140 && parse_date_delimiter (i)
1141 && parse_day (i, &day)
1142 && parse_date_delimiter (i)
1143 && parse_year (i, &year)
1144 && parse_trailer (i)
1145 && ymd_to_date (i, year, month, day, &i->v->f));
1149 parse_EDATE (struct data_in *i)
1151 long month, day, year;
1153 return (parse_leader (i)
1154 && parse_day (i, &day)
1155 && parse_date_delimiter (i)
1156 && parse_month (i, &month)
1157 && parse_date_delimiter (i)
1158 && parse_year (i, &year)
1159 && parse_trailer (i)
1160 && ymd_to_date (i, year, month, day, &i->v->f));
1164 parse_SDATE (struct data_in *i)
1166 long month, day, year;
1168 return (parse_leader (i)
1169 && parse_year (i, &year)
1170 && parse_date_delimiter (i)
1171 && parse_month (i, &month)
1172 && parse_date_delimiter (i)
1173 && parse_day (i, &day)
1174 && parse_trailer (i)
1175 && ymd_to_date (i, year, month, day, &i->v->f));
1179 parse_JDATE (struct data_in *i)
1184 if (!parse_leader (i)
1185 || !parse_julian (i, &julian)
1186 || !parse_trailer (i)
1187 || !ymd_to_ofs (i, julian / 1000, 1, 1, &ofs))
1190 i->v->f = (ofs + julian % 1000 - 1) * 60. * 60. * 24.;
1195 parse_QYR (struct data_in *i)
1199 return (parse_leader (i)
1200 && parse_quarter (i, &quarter)
1201 && parse_q_delimiter (i)
1202 && parse_year (i, &year)
1203 && parse_trailer (i)
1204 && ymd_to_date (i, year, (quarter - 1) * 3 + 1, 1, &i->v->f));
1208 parse_MOYR (struct data_in *i)
1212 return (parse_leader (i)
1213 && parse_month (i, &month)
1214 && parse_date_delimiter (i)
1215 && parse_year (i, &year)
1216 && parse_trailer (i)
1217 && ymd_to_date (i, year, month, 1, &i->v->f));
1221 parse_WKYR (struct data_in *i)
1226 if (!parse_leader (i)
1227 || !parse_week (i, &week)
1228 || !parse_wk_delimiter (i)
1229 || !parse_year (i, &year)
1230 || !parse_trailer (i))
1235 if (!ymd_to_ofs (i, year, 1, 1, &ofs))
1240 if (ymd_to_ofs (i, 1583, 1, 1, &ofs))
1245 i->v->f = (ofs + (week - 1) * 7) * 60. * 60. * 24.;
1250 parse_TIME (struct data_in *i)
1256 if (!parse_leader (i)
1257 || !parse_sign (i, &sign)
1258 || !parse_spaces (i)
1259 || !parse_hour (i, &hour)
1260 || !parse_time_delimiter (i)
1261 || !parse_minute (i, &minute)
1262 || !parse_opt_second (i, &second))
1265 i->v->f = (hour * 60. * 60. + minute * 60. + second) * sign;
1270 parse_DTIME (struct data_in *i)
1273 long day_count, hour;
1277 if (!parse_leader (i)
1278 || !parse_sign (i, &sign)
1279 || !parse_spaces (i)
1280 || !parse_day_count (i, &day_count)
1281 || !parse_time_delimiter (i)
1282 || !parse_hour (i, &hour)
1283 || !parse_time_delimiter (i)
1284 || !parse_minute (i, &minute)
1285 || !parse_opt_second (i, &second))
1288 i->v->f = (day_count * 60. * 60. * 24.
1296 parse_DATETIME (struct data_in *i)
1298 long day, month, year;
1303 if (!parse_leader (i)
1304 || !parse_day (i, &day)
1305 || !parse_date_delimiter (i)
1306 || !parse_month (i, &month)
1307 || !parse_date_delimiter (i)
1308 || !parse_year (i, &year)
1309 || !parse_time_delimiter (i)
1310 || !parse_hour24 (i, &hour24)
1311 || !parse_time_delimiter (i)
1312 || !parse_minute (i, &minute)
1313 || !parse_opt_second (i, &second)
1314 || !ymd_to_date (i, year, month, day, &i->v->f))
1317 i->v->f += hour24 * 60. * 60. + minute * 60. + second;
1322 parse_WKDAY (struct data_in *i)
1326 if (!parse_leader (i)
1327 || !parse_weekday (i, &weekday)
1328 || !parse_trailer (i))
1336 parse_MONTH (struct data_in *i)
1340 if (!parse_leader (i)
1341 || !parse_month (i, &month)
1342 || !parse_trailer (i))
1349 /* Main dispatcher. */
1352 default_result (struct data_in *i)
1354 const struct fmt_desc *const fmt = &formats[i->format.type];
1356 /* Default to SYSMIS or blanks. */
1357 if (fmt->cat & FCAT_STRING)
1358 memset (i->v->s, ' ', i->format.w);
1360 i->v->f = get_blanks();
1364 data_in (struct data_in *i)
1366 const struct fmt_desc *const fmt = &formats[i->format.type];
1368 assert (check_input_specifier (&i->format, 0));
1370 /* Check that we've got a string to work with. */
1371 if (i->e == i->s || i->format.w <= 0)
1377 i->f2 = i->f1 + (i->e - i->s) - 1;
1379 /* Make sure that the string isn't too long. */
1380 if (i->format.w > fmt->Imax_w)
1382 dls_error (i, _("Field too long (%d characters). Truncated after "
1384 i->format.w, fmt->Imax_w);
1385 i->format.w = fmt->Imax_w;
1388 if (fmt->cat & FCAT_BLANKS_SYSMIS)
1390 const unsigned char *cp;
1400 i->v->f = get_blanks();
1407 static bool (*const handlers[FMT_NUMBER_OF_FORMATS])(struct data_in *) =
1409 parse_numeric, parse_N, parse_numeric, parse_numeric,
1410 parse_numeric, parse_numeric, parse_numeric,
1411 parse_Z, parse_A, parse_AHEX, parse_IB, parse_P, parse_PIB,
1412 parse_PIBHEX, parse_PK, parse_RB, parse_RBHEX,
1413 NULL, NULL, NULL, NULL, NULL,
1414 parse_DATE, parse_EDATE, parse_SDATE, parse_ADATE, parse_JDATE,
1415 parse_QYR, parse_MOYR, parse_WKYR,
1416 parse_DATETIME, parse_TIME, parse_DTIME,
1417 parse_WKDAY, parse_MONTH,
1420 bool (*handler)(struct data_in *);
1423 handler = handlers[i->format.type];
1424 assert (handler != NULL);
1426 success = handler (i);
1434 /* Utility function. */
1436 /* Sets DI->{s,e} appropriately given that LINE has length LEN and the
1437 field starts at one-based column FC and ends at one-based column
1440 data_in_finite_line (struct data_in *di, const char *line, size_t len,
1443 di->s = line + ((size_t) fc <= len ? fc - 1 : len);
1444 di->e = line + ((size_t) lc <= len ? lc : len);