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
40 #include "debug-print.h"
43 /* Specialized error routine. */
45 static void dls_error (const struct data_in *, const char *format, ...)
49 vdls_error (const struct data_in *i, const char *format, va_list args)
54 if (i->flags & DI_IGNORE_ERROR)
58 if (!getl_reading_script)
59 ds_puts (&title, _("data-file error: "));
61 ds_printf (&title, _("(column %d"), i->f1);
63 ds_printf (&title, _("(columns %d-%d"), i->f1, i->f2);
64 ds_printf (&title, _(", field type %s) "), fmt_to_string (&i->format));
67 err_location (&e.where);
68 e.title = ds_c_str (&title);
70 err_vmsg (&e, format, args);
76 dls_error (const struct data_in *i, const char *format, ...)
80 va_start (args, format);
81 vdls_error (i, format, args);
85 /* Parsing utility functions. */
87 /* Excludes leading and trailing whitespace from I by adjusting
90 trim_whitespace (struct data_in *i)
92 while (i->s < i->e && isspace (i->s[0]))
95 while (i->s < i->e && isspace (i->e[-1]))
99 /* Returns nonzero if we're not at the end of the string being
102 have_char (struct data_in *i)
107 /* If implied decimal places are enabled, apply them to
110 apply_implied_decimals (struct data_in *i)
112 if ((i->flags & DI_IMPLIED_DECIMALS) && i->format.d > 0)
113 i->v->f /= pow (10., i->format.d);
116 /* Format parsers. */
118 static bool parse_int (struct data_in *i, long *result);
120 /* This function is based on strtod() from the GNU C library. */
122 parse_numeric (struct data_in *i)
124 int sign; /* +1 or -1. */
125 double num; /* The number so far. */
127 bool got_dot; /* Found a decimal point. */
128 size_t digit_cnt; /* Count of digits. */
130 int decimal; /* Decimal point character. */
131 int grouping; /* Grouping character. */
133 long int exponent; /* Number's exponent. */
134 int type; /* Usually same as i->format.type. */
138 type = i->format.type;
139 if (type == FMT_DOLLAR && have_char (i) && *i->s == '$')
148 sign = *i->s == '-' ? -1 : 1;
149 if (*i->s == '-' || *i->s == '+')
157 decimal = get_decimal();
158 grouping = get_grouping();
162 decimal = get_grouping();
163 grouping = get_decimal();
171 for (; have_char (i); i->s++)
177 /* Make sure that multiplication by 10 will not overflow. */
178 if (num > DBL_MAX * 0.1)
179 /* The value of the digit doesn't matter, since we have already
180 gotten as many digits as can be represented in a `double'.
181 This doesn't necessarily mean the result will overflow.
182 The exponent may reduce it to within range.
184 We just need to record that there was another
185 digit so that we can multiply by 10 later. */
188 num = (num * 10.0) + (*i->s - '0');
190 /* Keep track of the number of digits after the decimal point.
191 If we just divided by 10 here, we would lose precision. */
195 else if (!got_dot && *i->s == decimal)
196 /* Record that we have found the decimal point. */
198 else if ((type != FMT_COMMA && type != FMT_DOT) || *i->s != grouping)
199 /* Any other character terminates the number. */
210 dls_error (i, _("Field does not form a valid floating-point constant."));
215 if (have_char (i) && strchr ("eEdD-+", *i->s))
217 /* Get the exponent specified after the `e' or `E'. */
222 if (!parse_int (i, &exp))
230 else if (!got_dot && (i->flags & DI_IMPLIED_DECIMALS))
231 exponent -= i->format.d;
233 if (type == FMT_PCT && have_char (i) && *i->s == '%')
237 dls_error (i, _("Field contents followed by garbage."));
248 /* Multiply NUM by 10 to the EXPONENT power, checking for overflow
252 if (-exponent + digit_cnt > -(DBL_MIN_10_EXP) + 5
253 || num < DBL_MIN * pow (10.0, (double) -exponent))
255 dls_error (i, _("Underflow in floating-point constant."));
260 num *= pow (10.0, (double) exponent);
262 else if (exponent > 0)
264 if (num > DBL_MAX * pow (10.0, (double) -exponent))
266 dls_error (i, _("Overflow in floating-point constant."));
271 num *= pow (10.0, (double) exponent);
274 i->v->f = sign > 0 ? num : -num;
278 /* Returns the integer value of hex digit C. */
282 const char s[] = "0123456789abcdef";
283 const char *cp = strchr (s, tolower ((unsigned char) c));
290 parse_N (struct data_in *i)
292 const unsigned char *cp;
295 for (cp = i->s; cp < i->e; cp++)
299 dls_error (i, _("All characters in field must be digits."));
303 i->v->f = i->v->f * 10.0 + *cp - '0';
306 apply_implied_decimals (i);
311 parse_PIBHEX (struct data_in *i)
314 const unsigned char *cp;
319 for (cp = i->s; cp < i->e; cp++)
323 dls_error (i, _("Unrecognized character in field."));
327 n = n * 16.0 + hexit_value (*cp);
335 parse_RBHEX (struct data_in *i)
337 /* Validate input. */
339 if ((i->e - i->s) % 2)
341 dls_error (i, _("Field must have even length."));
346 const unsigned char *cp;
348 for (cp = i->s; cp < i->e; cp++)
351 dls_error (i, _("Field must contain only hex digits."));
361 unsigned char c[sizeof (double)];
367 memset (u.c, 0, sizeof u.c);
368 for (j = 0; j < min ((i->e - i->s) / 2, sizeof u.d); j++)
369 u.c[j] = 16 * hexit_value (i->s[j * 2]) + hexit_value (i->s[j * 2 + 1]);
378 parse_Z (struct data_in *i)
381 bool got_dot = false;
383 /* Warn user that we suck. */
390 _("Quality of zoned decimal (Z) input format code is "
391 "suspect. Check your results three times. Report bugs "
392 "to %s."),PACKAGE_BUGREPORT);
397 /* Validate input. */
402 dls_error (i, _("Zoned decimal field contains fewer than 2 "
407 /* Copy sign into buf[0]. */
408 if ((i->e[-1] & 0xc0) != 0xc0)
410 dls_error (i, _("Bad sign byte in zoned decimal number."));
413 buf[0] = (i->e[-1] ^ (i->e[-1] >> 1)) & 0x10 ? '-' : '+';
415 /* Copy digits into buf[1 ... len - 1] and terminate string. */
417 const unsigned char *sp;
420 for (sp = i->s, dp = buf + 1; sp < i->e - 1; sp++, dp++)
426 else if ((*sp & 0xf0) == 0xf0 && (*sp & 0xf) < 10)
427 *dp = (*sp & 0xf) + '0';
430 dls_error (i, _("Format error in zoned decimal number."));
437 /* Parse as number. */
441 i->v->f = strtod ((char *) buf, (char **) &tail);
442 if ((unsigned char *) tail != i->e)
444 dls_error (i, _("Error in syntax of zoned decimal number."));
450 apply_implied_decimals (i);
456 parse_IB (struct data_in *i)
463 /* We want the data to be in big-endian format. If this is a
464 little-endian machine, reverse the byte order. */
465 #ifdef WORDS_BIGENDIAN
468 memcpy (buf, i->s, i->e - i->s);
469 buf_reverse (buf, i->e - i->s);
473 /* If the value is negative, we need to logical-NOT each value
484 for (j = 0; j < i->e - i->s; j++)
485 i->v->f = i->v->f * 256.0 + (p[j] ^ xor);
488 /* If the value is negative, add 1 and set the sign, to complete a
489 two's-complement negation. */
491 i->v->f = -(i->v->f + 1.0);
493 apply_implied_decimals (i);
499 parse_PIB (struct data_in *i)
505 for (j = 0; j < i->e - i->s; j++)
506 i->v->f = i->v->f * 256.0 + i->s[j];
508 for (j = i->e - i->s - 1; j >= 0; j--)
509 i->v->f = i->v->f * 256.0 + i->s[j];
512 apply_implied_decimals (i);
518 parse_P (struct data_in *i)
520 const unsigned char *cp;
523 for (cp = i->s; cp < i->e - 1; cp++)
525 i->v->f = i->v->f * 10 + (*cp >> 4);
526 i->v->f = i->v->f * 10 + (*cp & 15);
528 i->v->f = i->v->f * 10 + (*cp >> 4);
529 if ((*cp ^ (*cp >> 1)) & 0x10)
532 apply_implied_decimals (i);
538 parse_PK (struct data_in *i)
540 const unsigned char *cp;
543 for (cp = i->s; cp < i->e; cp++)
545 i->v->f = i->v->f * 10 + (*cp >> 4);
546 i->v->f = i->v->f * 10 + (*cp & 15);
549 apply_implied_decimals (i);
555 parse_RB (struct data_in *i)
560 unsigned char c[sizeof (double)];
564 memset (u.c, 0, sizeof u.c);
565 memcpy (u.c, i->s, min ((int) sizeof (u.c), i->e - i->s));
572 parse_A (struct data_in *i)
574 ptrdiff_t len = i->e - i->s;
576 if (len >= i->format.w)
577 memcpy (i->v->s, i->s, i->format.w);
580 memcpy (i->v->s, i->s, len);
581 memset (i->v->s + len, ' ', i->format.w - len);
588 parse_AHEX (struct data_in *i)
590 /* Validate input. */
592 if ((i->e - i->s) % 2)
594 dls_error (i, _("Field must have even length."));
599 const unsigned char *cp;
601 for (cp = i->s; cp < i->e; cp++)
604 dls_error (i, _("Field must contain only hex digits."));
613 for (j = 0; j < min (i->e - i->s, i->format.w); j += 2)
614 i->v->s[j / 2] = hexit_value (i->s[j]) * 16 + hexit_value (i->s[j + 1]);
615 memset (i->v->s + (i->e - i->s) / 2, ' ', (i->format.w - (i->e - i->s)) / 2);
621 /* Date & time format components. */
623 /* Advances *CP past any whitespace characters. */
625 skip_whitespace (struct data_in *i)
627 while (isspace ((unsigned char) *i->s))
632 parse_leader (struct data_in *i)
639 force_have_char (struct data_in *i)
644 dls_error (i, _("Unexpected end of field."));
649 parse_int (struct data_in *i, long *result)
651 bool negative = false;
653 if (!force_have_char (i))
661 else if (*i->s == '-')
668 if (!isdigit (*i->s))
670 dls_error (i, _("Digit expected in field."));
677 *result = *result * 10 + *i->s++ - '0';
678 if (!have_char (i) || !isdigit (*i->s))
688 parse_day (struct data_in *i, long *day)
690 if (!parse_int (i, day))
692 if (*day >= 1 && *day <= 31)
695 dls_error (i, _("Day (%ld) must be between 1 and 31."), *day);
700 parse_day_count (struct data_in *i, long *day_count)
702 return parse_int (i, day_count);
706 parse_date_delimiter (struct data_in *i)
711 && (*i->s == '-' || *i->s == '/' || isspace (*i->s)
712 || *i->s == '.' || *i->s == ','))
720 dls_error (i, _("Delimiter expected between fields in date."));
724 /* Association between a name and a value. */
727 const char *name; /* Name. */
728 bool can_abbreviate; /* True if name may be abbreviated. */
729 int value; /* Value associated with name. */
732 /* Reads a name from I and sets *OUTPUT to the value associated
733 with that name. Returns true if successful, false otherwise. */
735 parse_enum (struct data_in *i, const char *what,
736 const struct enum_name *enum_names,
741 const struct enum_name *ep;
743 /* Consume alphabetic characters. */
746 while (have_char (i) && isalpha (*i->s))
753 dls_error (i, _("Parse error at `%c' expecting %s."), *i->s, what);
757 for (ep = enum_names; ep->name != NULL; ep++)
758 if ((ep->can_abbreviate
759 && lex_id_match_len (ep->name, strlen (ep->name), name, length))
760 || (!ep->can_abbreviate && length == strlen (ep->name)
761 && !buf_compare_case (name, ep->name, length)))
767 dls_error (i, _("Unknown %s `%.*s'."), what, (int) length, name);
772 parse_month (struct data_in *i, long *month)
774 static const struct enum_name month_names[] =
776 {"january", true, 1},
777 {"february", true, 2},
784 {"september", true, 9},
785 {"october", true, 10},
786 {"november", true, 11},
787 {"december", true, 12},
807 if (!force_have_char (i))
812 if (!parse_int (i, month))
814 if (*month >= 1 && *month <= 12)
817 dls_error (i, _("Month (%ld) must be between 1 and 12."), *month);
821 return parse_enum (i, _("month"), month_names, month);
825 parse_year (struct data_in *i, long *year)
827 if (!parse_int (i, year))
830 if (*year >= 0 && *year <= 199)
832 if (*year >= 1582 || *year <= 19999)
835 dls_error (i, _("Year (%ld) must be between 1582 and 19999."), *year);
840 parse_trailer (struct data_in *i)
846 dls_error (i, _("Trailing garbage \"%s\" following date."), i->s);
851 parse_julian (struct data_in *i, long *julian)
853 if (!parse_int (i, julian))
857 int day = *julian % 1000;
859 if (day < 1 || day > 366)
861 dls_error (i, _("Julian day (%d) must be between 1 and 366."), day);
867 int year = *julian / 1000;
869 if (year >= 0 && year <= 199)
871 else if (year < 1582 || year > 19999)
873 dls_error (i, _("Year (%d) must be between 1582 and 19999."), year);
882 parse_quarter (struct data_in *i, long *quarter)
884 if (!parse_int (i, quarter))
886 if (*quarter >= 1 && *quarter <= 4)
889 dls_error (i, _("Quarter (%ld) must be between 1 and 4."), *quarter);
894 parse_q_delimiter (struct data_in *i)
897 if (!have_char (i) || tolower (*i->s) != 'q')
899 dls_error (i, _("`Q' expected between quarter and year."));
908 parse_week (struct data_in *i, long *week)
910 if (!parse_int (i, week))
912 if (*week >= 1 && *week <= 53)
915 dls_error (i, _("Week (%ld) must be between 1 and 53."), *week);
920 parse_wk_delimiter (struct data_in *i)
924 || tolower (i->s[0]) != 'w' || tolower (i->s[1]) != 'k')
926 dls_error (i, _("`WK' expected between week and year."));
935 parse_time_delimiter (struct data_in *i)
939 while (have_char (i) && (*i->s == ':' || *i->s == '.' || isspace (*i->s)))
948 dls_error (i, _("Delimiter expected between fields in time."));
953 parse_hour (struct data_in *i, long *hour)
955 if (!parse_int (i, hour))
960 dls_error (i, _("Hour (%ld) must be positive."), *hour);
965 parse_minute (struct data_in *i, long *minute)
967 if (!parse_int (i, minute))
969 if (*minute >= 0 && *minute <= 59)
972 dls_error (i, _("Minute (%ld) must be between 0 and 59."), *minute);
977 parse_opt_second (struct data_in *i, double *second)
985 && (*i->s == ':' || *i->s == '.' || isspace (*i->s)))
991 if (!delim || !isdigit (*i->s))
998 while (have_char (i) && isdigit (*i->s))
1000 if (have_char (i) && *i->s == '.')
1002 while (have_char (i) && isdigit (*i->s))
1006 *second = strtod (buf, NULL);
1012 parse_hour24 (struct data_in *i, long *hour24)
1014 if (!parse_int (i, hour24))
1016 if (*hour24 >= 0 && *hour24 <= 23)
1019 dls_error (i, _("Hour (%ld) must be between 0 and 23."), *hour24);
1025 parse_weekday (struct data_in *i, long *weekday)
1027 static const struct enum_name weekday_names[] =
1029 {"sunday", true, 1},
1031 {"monday", true, 2},
1033 {"tuesday", true, 3},
1035 {"wednesday", true, 4},
1037 {"thursday", true, 5},
1039 {"friday", true, 6},
1041 {"saturday", true, 7},
1047 return parse_enum (i, _("weekday"), weekday_names, weekday);
1051 parse_spaces (struct data_in *i)
1053 skip_whitespace (i);
1058 parse_sign (struct data_in *i, int *sign)
1060 if (!force_have_char (i))
1082 /* Date & time formats. */
1085 calendar_error (void *i_, const char *format, ...)
1087 struct data_in *i = i_;
1090 va_start (args, format);
1091 vdls_error (i, format, args);
1096 ymd_to_ofs (struct data_in *i, int year, int month, int day, double *ofs)
1098 *ofs = calendar_gregorian_to_offset (year, month, day, calendar_error, i);
1099 return *ofs != SYSMIS;
1103 ymd_to_date (struct data_in *i, int year, int month, int day, double *date)
1105 if (ymd_to_ofs (i, year, month, day, date))
1107 *date *= 60. * 60. * 24.;
1115 parse_DATE (struct data_in *i)
1117 long day, month, year;
1119 return (parse_leader (i)
1120 && parse_day (i, &day)
1121 && parse_date_delimiter (i)
1122 && parse_month (i, &month)
1123 && parse_date_delimiter (i)
1124 && parse_year (i, &year)
1125 && parse_trailer (i)
1126 && ymd_to_date (i, year, month, day, &i->v->f));
1130 parse_ADATE (struct data_in *i)
1132 long month, day, year;
1134 return (parse_leader (i)
1135 && parse_month (i, &month)
1136 && parse_date_delimiter (i)
1137 && parse_day (i, &day)
1138 && parse_date_delimiter (i)
1139 && parse_year (i, &year)
1140 && parse_trailer (i)
1141 && ymd_to_date (i, year, month, day, &i->v->f));
1145 parse_EDATE (struct data_in *i)
1147 long month, day, year;
1149 return (parse_leader (i)
1150 && parse_day (i, &day)
1151 && parse_date_delimiter (i)
1152 && parse_month (i, &month)
1153 && parse_date_delimiter (i)
1154 && parse_year (i, &year)
1155 && parse_trailer (i)
1156 && ymd_to_date (i, year, month, day, &i->v->f));
1160 parse_SDATE (struct data_in *i)
1162 long month, day, year;
1164 return (parse_leader (i)
1165 && parse_year (i, &year)
1166 && parse_date_delimiter (i)
1167 && parse_month (i, &month)
1168 && parse_date_delimiter (i)
1169 && parse_day (i, &day)
1170 && parse_trailer (i)
1171 && ymd_to_date (i, year, month, day, &i->v->f));
1175 parse_JDATE (struct data_in *i)
1180 if (!parse_leader (i)
1181 || !parse_julian (i, &julian)
1182 || !parse_trailer (i)
1183 || !ymd_to_ofs (i, julian / 1000, 1, 1, &ofs))
1186 i->v->f = (ofs + julian % 1000 - 1) * 60. * 60. * 24.;
1191 parse_QYR (struct data_in *i)
1195 return (parse_leader (i)
1196 && parse_quarter (i, &quarter)
1197 && parse_q_delimiter (i)
1198 && parse_year (i, &year)
1199 && parse_trailer (i)
1200 && ymd_to_date (i, year, (quarter - 1) * 3 + 1, 1, &i->v->f));
1204 parse_MOYR (struct data_in *i)
1208 return (parse_leader (i)
1209 && parse_month (i, &month)
1210 && parse_date_delimiter (i)
1211 && parse_year (i, &year)
1212 && parse_trailer (i)
1213 && ymd_to_date (i, year, month, 1, &i->v->f));
1217 parse_WKYR (struct data_in *i)
1222 if (!parse_leader (i)
1223 || !parse_week (i, &week)
1224 || !parse_wk_delimiter (i)
1225 || !parse_year (i, &year)
1226 || !parse_trailer (i))
1231 if (!ymd_to_ofs (i, year, 1, 1, &ofs))
1236 if (ymd_to_ofs (i, 1583, 1, 1, &ofs))
1241 i->v->f = (ofs + (week - 1) * 7) * 60. * 60. * 24.;
1246 parse_TIME (struct data_in *i)
1252 if (!parse_leader (i)
1253 || !parse_sign (i, &sign)
1254 || !parse_spaces (i)
1255 || !parse_hour (i, &hour)
1256 || !parse_time_delimiter (i)
1257 || !parse_minute (i, &minute)
1258 || !parse_opt_second (i, &second))
1261 i->v->f = (hour * 60. * 60. + minute * 60. + second) * sign;
1266 parse_DTIME (struct data_in *i)
1269 long day_count, hour;
1273 if (!parse_leader (i)
1274 || !parse_sign (i, &sign)
1275 || !parse_spaces (i)
1276 || !parse_day_count (i, &day_count)
1277 || !parse_time_delimiter (i)
1278 || !parse_hour (i, &hour)
1279 || !parse_time_delimiter (i)
1280 || !parse_minute (i, &minute)
1281 || !parse_opt_second (i, &second))
1284 i->v->f = (day_count * 60. * 60. * 24.
1292 parse_DATETIME (struct data_in *i)
1294 long day, month, year;
1299 if (!parse_leader (i)
1300 || !parse_day (i, &day)
1301 || !parse_date_delimiter (i)
1302 || !parse_month (i, &month)
1303 || !parse_date_delimiter (i)
1304 || !parse_year (i, &year)
1305 || !parse_time_delimiter (i)
1306 || !parse_hour24 (i, &hour24)
1307 || !parse_time_delimiter (i)
1308 || !parse_minute (i, &minute)
1309 || !parse_opt_second (i, &second)
1310 || !ymd_to_date (i, year, month, day, &i->v->f))
1313 i->v->f += hour24 * 60. * 60. + minute * 60. + second;
1318 parse_WKDAY (struct data_in *i)
1322 if (!parse_leader (i)
1323 || !parse_weekday (i, &weekday)
1324 || !parse_trailer (i))
1332 parse_MONTH (struct data_in *i)
1336 if (!parse_leader (i)
1337 || !parse_month (i, &month)
1338 || !parse_trailer (i))
1345 /* Main dispatcher. */
1348 default_result (struct data_in *i)
1350 const struct fmt_desc *const fmt = &formats[i->format.type];
1352 /* Default to SYSMIS or blanks. */
1353 if (fmt->cat & FCAT_STRING)
1354 memset (i->v->s, ' ', i->format.w);
1356 i->v->f = get_blanks();
1360 data_in (struct data_in *i)
1362 const struct fmt_desc *const fmt = &formats[i->format.type];
1364 assert (check_input_specifier (&i->format, 0));
1366 /* Check that we've got a string to work with. */
1367 if (i->e == i->s || i->format.w <= 0)
1373 i->f2 = i->f1 + (i->e - i->s) - 1;
1375 /* Make sure that the string isn't too long. */
1376 if (i->format.w > fmt->Imax_w)
1378 dls_error (i, _("Field too long (%d characters). Truncated after "
1380 i->format.w, fmt->Imax_w);
1381 i->format.w = fmt->Imax_w;
1384 if (fmt->cat & FCAT_BLANKS_SYSMIS)
1386 const unsigned char *cp;
1396 i->v->f = get_blanks();
1403 static bool (*const handlers[FMT_NUMBER_OF_FORMATS])(struct data_in *) =
1405 parse_numeric, parse_N, parse_numeric, parse_numeric,
1406 parse_numeric, parse_numeric, parse_numeric,
1407 parse_Z, parse_A, parse_AHEX, parse_IB, parse_P, parse_PIB,
1408 parse_PIBHEX, parse_PK, parse_RB, parse_RBHEX,
1409 NULL, NULL, NULL, NULL, NULL,
1410 parse_DATE, parse_EDATE, parse_SDATE, parse_ADATE, parse_JDATE,
1411 parse_QYR, parse_MOYR, parse_WKYR,
1412 parse_DATETIME, parse_TIME, parse_DTIME,
1413 parse_WKDAY, parse_MONTH,
1416 bool (*handler)(struct data_in *);
1419 handler = handlers[i->format.type];
1420 assert (handler != NULL);
1422 success = handler (i);
1430 /* Utility function. */
1432 /* Sets DI->{s,e} appropriately given that LINE has length LEN and the
1433 field starts at one-based column FC and ends at one-based column
1436 data_in_finite_line (struct data_in *di, const char *line, size_t len,
1439 di->s = line + ((size_t) fc <= len ? fc - 1 : len);
1440 di->e = line + ((size_t) lc <= len ? lc : len);