X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata-in.c;h=8f36dcb046d298c3e431b59fc53617c939ca4113;hb=1195caf0c998e80d3e7195a0452a14e7b4194077;hp=c082516d664efe45f39f6eaf31a1b439c0cdfb3b;hpb=92bfefccd465052e492f669ce561aa25b0110283;p=pspp-builds.git diff --git a/src/data-in.c b/src/data-in.c index c082516d..8f36dcb0 100644 --- a/src/data-in.c +++ b/src/data-in.c @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ #include #include "data-in.h" @@ -26,9 +26,10 @@ #include #include #include +#include "bool.h" #include "error.h" #include "getline.h" -#include "julcal/julcal.h" +#include "calendar.h" #include "lexer.h" #include "magic.h" #include "misc.h" @@ -45,45 +46,44 @@ static void dls_error (const struct data_in *, const char *format, ...) PRINTF_FORMAT (2, 3); static void -dls_error (const struct data_in *i, const char *format, ...) +vdls_error (const struct data_in *i, const char *format, va_list args) { - char buf[1024]; + struct error e; + struct string title; if (i->flags & DI_IGNORE_ERROR) return; - { - va_list args; - - va_start (args, format); - snprintf (buf, 1024, format, args); - va_end (args); - } - - { - struct error e; - struct string title; - - ds_init (&title, 64); - if (!getl_reading_script) - ds_puts (&title, _("data-file error: ")); - if (i->f1 == i->f2) - ds_printf (&title, _("(column %d"), i->f1); - else - ds_printf (&title, _("(columns %d-%d"), i->f1, i->f2); - ds_printf (&title, _(", field type %s) "), fmt_to_string (&i->format)); + ds_init (&title, 64); + if (!getl_reading_script) + ds_puts (&title, _("data-file error: ")); + if (i->f1 == i->f2) + ds_printf (&title, _("(column %d"), i->f1); + else + ds_printf (&title, _("(columns %d-%d"), i->f1, i->f2); + ds_printf (&title, _(", field type %s) "), fmt_to_string (&i->format)); - e.class = DE; - err_location (&e.where); - e.title = ds_c_str (&title); - e.text = buf; + e.class = DE; + err_location (&e.where); + e.title = ds_c_str (&title); - err_vmsg (&e); + err_vmsg (&e, format, args); - ds_destroy (&title); - } + ds_destroy (&title); } +static void +dls_error (const struct data_in *i, const char *format, ...) +{ + va_list args; + + va_start (args, format); + vdls_error (i, format, args); + va_end (args); +} + +/* Parsing utility functions. */ + /* Excludes leading and trailing whitespace from I by adjusting pointers. */ static void @@ -98,25 +98,34 @@ trim_whitespace (struct data_in *i) /* Returns nonzero if we're not at the end of the string being parsed. */ -static inline int +static inline bool have_char (struct data_in *i) { return i->s < i->e; } + +/* If implied decimal places are enabled, apply them to + I->v->f. */ +static void +apply_implied_decimals (struct data_in *i) +{ + if ((i->flags & DI_IMPLIED_DECIMALS) && i->format.d > 0) + i->v->f /= pow (10., i->format.d); +} /* Format parsers. */ -static int parse_int (struct data_in *i, long *result); +static bool parse_int (struct data_in *i, long *result); /* This function is based on strtod() from the GNU C library. */ -static int +static bool parse_numeric (struct data_in *i) { - short int sign; /* +1 or -1. */ + int sign; /* +1 or -1. */ double num; /* The number so far. */ - int got_dot; /* Found a decimal point. */ - int got_digit; /* Count of digits. */ + bool got_dot; /* Found a decimal point. */ + size_t digit_cnt; /* Count of digits. */ int decimal; /* Decimal point character. */ int grouping; /* Grouping character. */ @@ -156,14 +165,14 @@ parse_numeric (struct data_in *i) i->v->f = SYSMIS; num = 0.0; - got_dot = 0; - got_digit = 0; + got_dot = false; + digit_cnt = 0; exponent = 0; for (; have_char (i); i->s++) { if (isdigit (*i->s)) { - got_digit++; + digit_cnt++; /* Make sure that multiplication by 10 will not overflow. */ if (num > DBL_MAX * 0.1) @@ -185,20 +194,22 @@ parse_numeric (struct data_in *i) } else if (!got_dot && *i->s == decimal) /* Record that we have found the decimal point. */ - got_dot = 1; + got_dot = true; else if ((type != FMT_COMMA && type != FMT_DOT) || *i->s != grouping) /* Any other character terminates the number. */ break; } - if (!got_digit) + if (!digit_cnt) { if (got_dot) { i->v->f = SYSMIS; - return 1; + return true; } - goto noconv; + dls_error (i, _("Field does not form a valid floating-point constant.")); + i->v->f = SYSMIS; + return false; } if (have_char (i) @@ -211,11 +222,14 @@ parse_numeric (struct data_in *i) if (isalpha (*i->s)) i->s++; if (!parse_int (i, &exp)) - goto noconv; + { + i->v->f = SYSMIS; + return false; + } exponent += exp; } - else if (!got_dot) + else if (!got_dot && (i->flags & DI_IMPLIED_DECIMALS)) exponent -= i->format.d; if (type == FMT_PCT && have_char (i) && *i->s == '%') @@ -224,52 +238,43 @@ parse_numeric (struct data_in *i) { dls_error (i, _("Field contents followed by garbage.")); i->v->f = SYSMIS; - return 0; + return false; } if (num == 0.0) { i->v->f = 0.0; - return 1; + return true; } /* Multiply NUM by 10 to the EXPONENT power, checking for overflow and underflow. */ - if (exponent < 0) { - if (-exponent + got_digit > -(DBL_MIN_10_EXP) + 5 - || num < DBL_MIN * pow (10.0, (double) -exponent)) - goto underflow; + if (-exponent + digit_cnt > -(DBL_MIN_10_EXP) + 5 + || num < DBL_MIN * pow (10.0, (double) -exponent)) + { + dls_error (i, _("Underflow in floating-point constant.")); + i->v->f = 0.0; + return false; + } + num *= pow (10.0, (double) exponent); } else if (exponent > 0) { if (num > DBL_MAX * pow (10.0, (double) -exponent)) - goto overflow; + { + dls_error (i, _("Overflow in floating-point constant.")); + i->v->f = SYSMIS; + return false; + } + num *= pow (10.0, (double) exponent); } - i->v->f = sign * num; - return 1; - -overflow: - /* Return an overflow error. */ - dls_error (i, _("Overflow in floating-point constant.")); - i->v->f = SYSMIS; - return 0; - -underflow: - /* Return an underflow error. */ - dls_error (i, _("Underflow in floating-point constant.")); - i->v->f = 0.0; - return 0; - -noconv: - /* There was no number. */ - dls_error (i, _("Field does not form a valid floating-point constant.")); - i->v->f = SYSMIS; - return 0; + i->v->f = sign > 0 ? num : -num; + return true; } /* Returns the integer value of hex digit C. */ @@ -283,7 +288,7 @@ hexit_value (int c) return cp - s; } -static inline int +static inline bool parse_N (struct data_in *i) { const unsigned char *cp; @@ -294,18 +299,17 @@ parse_N (struct data_in *i) if (!isdigit (*cp)) { dls_error (i, _("All characters in field must be digits.")); - return 0; + return false; } i->v->f = i->v->f * 10.0 + *cp - '0'; } - if (i->format.d) - i->v->f /= pow (10.0, i->format.d); - return 1; + apply_implied_decimals (i); + return true; } -static inline int +static inline bool parse_PIBHEX (struct data_in *i) { double n; @@ -319,17 +323,17 @@ parse_PIBHEX (struct data_in *i) if (!isxdigit (*cp)) { dls_error (i, _("Unrecognized character in field.")); - return 0; + return false; } n = n * 16.0 + hexit_value (*cp); } i->v->f = n; - return 1; + return true; } -static inline int +static inline bool parse_RBHEX (struct data_in *i) { /* Validate input. */ @@ -337,7 +341,7 @@ parse_RBHEX (struct data_in *i) if ((i->e - i->s) % 2) { dls_error (i, _("Field must have even length.")); - return 0; + return false; } { @@ -347,7 +351,7 @@ parse_RBHEX (struct data_in *i) if (!isxdigit (*cp)) { dls_error (i, _("Field must contain only hex digits.")); - return 0; + return false; } } @@ -369,17 +373,18 @@ parse_RBHEX (struct data_in *i) i->v->f = u.d; } - return 1; + return true; } -static inline int +static inline bool parse_Z (struct data_in *i) { char buf[64]; + bool got_dot = false; /* Warn user that we suck. */ { - static int warned; + static bool warned; if (!warned) { @@ -387,7 +392,7 @@ parse_Z (struct data_in *i) _("Quality of zoned decimal (Z) input format code is " "suspect. Check your results three times. Report bugs " "to %s."),PACKAGE_BUGREPORT); - warned = 1; + warned = true; } } @@ -398,14 +403,14 @@ parse_Z (struct data_in *i) { dls_error (i, _("Zoned decimal field contains fewer than 2 " "characters.")); - return 0; + return false; } /* Copy sign into buf[0]. */ if ((i->e[-1] & 0xc0) != 0xc0) { dls_error (i, _("Bad sign byte in zoned decimal number.")); - return 0; + return false; } buf[0] = (i->e[-1] ^ (i->e[-1] >> 1)) & 0x10 ? '-' : '+'; @@ -415,14 +420,17 @@ parse_Z (struct data_in *i) char *dp; for (sp = i->s, dp = buf + 1; sp < i->e - 1; sp++, dp++) - if (*sp == '.') - *dp = '.'; + if (*sp == '.') + { + *dp = '.'; + got_dot = true; + } else if ((*sp & 0xf0) == 0xf0 && (*sp & 0xf) < 10) *dp = (*sp & 0xf) + '0'; else { dls_error (i, _("Format error in zoned decimal number.")); - return 0; + return false; } *dp = '\0'; @@ -436,14 +444,17 @@ parse_Z (struct data_in *i) if ((unsigned char *) tail != i->e) { dls_error (i, _("Error in syntax of zoned decimal number.")); - return 0; + return false; } } - - return 1; + + if (!got_dot) + apply_implied_decimals (i); + + return true; } -static inline int +static inline bool parse_IB (struct data_in *i) { char buf[64]; @@ -481,13 +492,12 @@ parse_IB (struct data_in *i) if (p[0] & 0x80) i->v->f = -(i->v->f + 1.0); - if (i->format.d) - i->v->f /= pow (10.0, i->format.d); + apply_implied_decimals (i); - return 1; + return true; } -static inline int +static inline bool parse_PIB (struct data_in *i) { int j; @@ -501,13 +511,12 @@ parse_PIB (struct data_in *i) i->v->f = i->v->f * 256.0 + i->s[j]; #endif - if (i->format.d) - i->v->f /= pow (10.0, i->format.d); + apply_implied_decimals (i); - return 1; + return true; } -static inline int +static inline bool parse_P (struct data_in *i) { const unsigned char *cp; @@ -522,13 +531,12 @@ parse_P (struct data_in *i) if ((*cp ^ (*cp >> 1)) & 0x10) i->v->f = -i->v->f; - if (i->format.d) - i->v->f /= pow (10.0, i->format.d); + apply_implied_decimals (i); - return 1; + return true; } -static inline int +static inline bool parse_PK (struct data_in *i) { const unsigned char *cp; @@ -540,13 +548,12 @@ parse_PK (struct data_in *i) i->v->f = i->v->f * 10 + (*cp & 15); } - if (i->format.d) - i->v->f /= pow (10.0, i->format.d); + apply_implied_decimals (i); - return 1; + return true; } -static inline int +static inline bool parse_RB (struct data_in *i) { union @@ -560,10 +567,10 @@ parse_RB (struct data_in *i) memcpy (u.c, i->s, min ((int) sizeof (u.c), i->e - i->s)); i->v->f = u.d; - return 1; + return true; } -static inline int +static inline bool parse_A (struct data_in *i) { ptrdiff_t len = i->e - i->s; @@ -576,10 +583,10 @@ parse_A (struct data_in *i) memset (i->v->s + len, ' ', i->format.w - len); } - return 1; + return true; } -static inline int +static inline bool parse_AHEX (struct data_in *i) { /* Validate input. */ @@ -587,7 +594,7 @@ parse_AHEX (struct data_in *i) if ((i->e - i->s) % 2) { dls_error (i, _("Field must have even length.")); - return 0; + return false; } { @@ -597,7 +604,7 @@ parse_AHEX (struct data_in *i) if (!isxdigit (*cp)) { dls_error (i, _("Field must contain only hex digits.")); - return 0; + return false; } } @@ -610,7 +617,7 @@ parse_AHEX (struct data_in *i) memset (i->v->s + (i->e - i->s) / 2, ' ', (i->format.w - (i->e - i->s)) / 2); } - return 1; + return true; } /* Date & time format components. */ @@ -623,30 +630,30 @@ skip_whitespace (struct data_in *i) i->s++; } -static inline int +static inline bool parse_leader (struct data_in *i) { skip_whitespace (i); - return 1; + return true; } -static inline int +static inline bool force_have_char (struct data_in *i) { if (have_char (i)) - return 1; + return true; dls_error (i, _("Unexpected end of field.")); - return 0; + return false; } -static int +static bool parse_int (struct data_in *i, long *result) { - int negative = 0; + bool negative = false; if (!force_have_char (i)) - return 0; + return false; if (*i->s == '+') { @@ -655,7 +662,7 @@ parse_int (struct data_in *i, long *result) } else if (*i->s == '-') { - negative = 1; + negative = true; i->s++; force_have_char (i); } @@ -663,7 +670,7 @@ parse_int (struct data_in *i, long *result) if (!isdigit (*i->s)) { dls_error (i, _("Digit expected in field.")); - return 0; + return false; } *result = 0; @@ -676,254 +683,177 @@ parse_int (struct data_in *i, long *result) if (negative) *result = -*result; - return 1; + return true; } -static int +static bool parse_day (struct data_in *i, long *day) { if (!parse_int (i, day)) - return 0; + return false; if (*day >= 1 && *day <= 31) - return 1; + return true; dls_error (i, _("Day (%ld) must be between 1 and 31."), *day); - return 0; + return false; } -static int +static bool parse_day_count (struct data_in *i, long *day_count) { return parse_int (i, day_count); } -static int +static bool parse_date_delimiter (struct data_in *i) { - int delim = 0; + bool delim = false; while (have_char (i) && (*i->s == '-' || *i->s == '/' || isspace (*i->s) || *i->s == '.' || *i->s == ',')) { - delim = 1; + delim = true; i->s++; } if (delim) - return 1; + return true; dls_error (i, _("Delimiter expected between fields in date.")); - return 0; + return false; } -/* Formats NUMBER as Roman numerals in ROMAN, or as Arabic numerals if - the Roman expansion would be too long. */ -static void -to_roman (int number, char roman[32]) -{ - int save_number = number; - - struct roman_digit - { - int value; /* Value corresponding to this digit. */ - char name; /* Digit name. */ - }; - - static const struct roman_digit roman_tab[7] = +/* Association between a name and a value. */ +struct enum_name { - {1000, 'M'}, - {500, 'D'}, - {100, 'C'}, - {50, 'L'}, - {10, 'X'}, - {5, 'V'}, - {1, 'I'}, + const char *name; /* Name. */ + bool can_abbreviate; /* True if name may be abbreviated. */ + int value; /* Value associated with name. */ }; - char *cp = roman; - - int i, j; - - assert (32 >= INT_DIGITS + 1); - if (number == 0) - goto arabic; - - if (number < 0) +/* Reads a name from I and sets *OUTPUT to the value associated + with that name. Returns true if successful, false otherwise. */ +static bool +parse_enum (struct data_in *i, const char *what, + const struct enum_name *enum_names, + long *output) +{ + const char *name; + size_t length; + const struct enum_name *ep; + + /* Consume alphabetic characters. */ + name = i->s; + length = 0; + while (have_char (i) && isalpha (*i->s)) { - *cp++ = '-'; - number = -number; + length++; + i->s++; } - - for (i = 0; i < 7; i++) + if (length == 0) { - int digit = roman_tab[i].value; - while (number >= digit) - { - number -= digit; - if (cp > &roman[30]) - goto arabic; - *cp++ = roman_tab[i].name; - } - - for (j = i + 1; j < 7; j++) - { - if (i == 4 && j == 5) /* VX is not a shortened form of V. */ - break; - - digit = roman_tab[i].value - roman_tab[j].value; - while (number >= digit) - { - number -= digit; - if (cp > &roman[29]) - goto arabic; - *cp++ = roman_tab[j].name; - *cp++ = roman_tab[i].name; - } - } + dls_error (i, _("Parse error at `%c' expecting %s."), *i->s, what); + return false; } - *cp = 0; - return; - -arabic: - sprintf (roman, "%d", save_number); -} -/* Returns true if C is a (lowercase) roman numeral. */ -#define CHAR_IS_ROMAN(C) \ - ((C) == 'x' || (C) == 'v' || (C) == 'i') + for (ep = enum_names; ep->name != NULL; ep++) + if ((ep->can_abbreviate + && lex_id_match_len (ep->name, strlen (ep->name), name, length)) + || (!ep->can_abbreviate && length == strlen (ep->name) + && !mm_case_compare (name, ep->name, length))) + { + *output = ep->value; + return true; + } -/* Returns the value of a single (lowercase) roman numeral. */ -#define ROMAN_VALUE(C) \ - ((C) == 'x' ? 10 : ((C) == 'v' ? 5 : 1)) + dls_error (i, _("Unknown %s `%.*s'."), what, (int) length, name); + return false; +} -static int +static bool parse_month (struct data_in *i, long *month) { + static const struct enum_name month_names[] = + { + {"january", true, 1}, + {"february", true, 2}, + {"march", true, 3}, + {"april", true, 4}, + {"may", true, 5}, + {"june", true, 6}, + {"july", true, 7}, + {"august", true, 8}, + {"september", true, 9}, + {"october", true, 10}, + {"november", true, 11}, + {"december", true, 12}, + + {"i", false, 1}, + {"ii", false, 2}, + {"iii", false, 3}, + {"iv", false, 4}, + {"iiii", false, 4}, + {"v", false, 5}, + {"vi", false, 6}, + {"vii", false, 7}, + {"viii", false, 8}, + {"ix", false, 9}, + {"viiii", false, 9}, + {"x", false, 10}, + {"xi", false, 11}, + {"xii", false, 12}, + + {NULL, false, 0}, + }; + if (!force_have_char (i)) - return 0; + return false; if (isdigit (*i->s)) { if (!parse_int (i, month)) - return 0; + return false; if (*month >= 1 && *month <= 12) - return 1; + return true; dls_error (i, _("Month (%ld) must be between 1 and 12."), *month); - return 0; - } - - if (CHAR_IS_ROMAN (tolower (*i->s))) - { - int last = ROMAN_VALUE (tolower (*i->s)); - - *month = 0; - for (;;) - { - int value; - - i->s++; - if (!have_char || !CHAR_IS_ROMAN (tolower (*i->s))) - { - if (last != INT_MAX) - *month += last; - break; - } - - value = ROMAN_VALUE (tolower (*i->s)); - if (last == INT_MAX) - *month += value; - else if (value > last) - { - *month += value - last; - last = INT_MAX; - } - else - { - *month += last; - last = value; - } - } - - if (*month < 1 || *month > 12) - { - char buf[32]; - - to_roman (*month, buf); - dls_error (i, _("Month (%s) must be between I and XII."), buf); - return 0; - } - - return 1; + return false; } - - { - static const char *months[12] = - { - "january", "february", "march", "april", "may", "june", - "july", "august", "september", "october", "november", "december", - }; - - char month_buf[32]; - char *mp; - - int j; - - for (mp = month_buf; - have_char (i) && isalpha (*i->s) && mp < &month_buf[31]; - i->s++) - *mp++ = tolower (*i->s); - *mp = '\0'; - - if (have_char (i) && isalpha (*i->s)) - { - dls_error (i, _("Month name (%s...) is too long."), month_buf); - return 0; - } - - for (j = 0; j < 12; j++) - if (lex_id_match (months[j], month_buf)) - { - *month = j + 1; - return 1; - } - - dls_error (i, _("Bad month name (%s)."), month_buf); - return 0; - } + else + return parse_enum (i, _("month"), month_names, month); } -static int +static bool parse_year (struct data_in *i, long *year) { if (!parse_int (i, year)) - return 0; + return false; if (*year >= 0 && *year <= 199) *year += 1900; if (*year >= 1582 || *year <= 19999) - return 1; + return true; dls_error (i, _("Year (%ld) must be between 1582 and 19999."), *year); - return 0; + return false; } -static int +static bool parse_trailer (struct data_in *i) { skip_whitespace (i); if (!have_char (i)) - return 1; + return true; dls_error (i, _("Trailing garbage \"%s\" following date."), i->s); - return 0; + return false; } -static int +static bool parse_julian (struct data_in *i, long *julian) { if (!parse_int (i, julian)) - return 0; + return false; { int day = *julian % 1000; @@ -931,7 +861,7 @@ parse_julian (struct data_in *i, long *julian) if (day < 1 || day > 366) { dls_error (i, _("Julian day (%d) must be between 1 and 366."), day); - return 0; + return false; } } @@ -943,52 +873,52 @@ parse_julian (struct data_in *i, long *julian) else if (year < 1582 || year > 19999) { dls_error (i, _("Year (%d) must be between 1582 and 19999."), year); - return 0; + return false; } } - return 1; + return true; } -static int +static bool parse_quarter (struct data_in *i, long *quarter) { if (!parse_int (i, quarter)) - return 0; + return false; if (*quarter >= 1 && *quarter <= 4) - return 1; + return true; dls_error (i, _("Quarter (%ld) must be between 1 and 4."), *quarter); - return 0; + return false; } -static int +static bool parse_q_delimiter (struct data_in *i) { skip_whitespace (i); if (!have_char (i) || tolower (*i->s) != 'q') { dls_error (i, _("`Q' expected between quarter and year.")); - return 0; + return false; } i->s++; skip_whitespace (i); - return 1; + return true; } -static int +static bool parse_week (struct data_in *i, long *week) { if (!parse_int (i, week)) - return 0; + return false; if (*week >= 1 && *week <= 53) - return 1; + return true; dls_error (i, _("Week (%ld) must be between 1 and 53."), *week); - return 0; + return false; } -static int +static bool parse_wk_delimiter (struct data_in *i) { skip_whitespace (i); @@ -996,60 +926,59 @@ parse_wk_delimiter (struct data_in *i) || tolower (i->s[0]) != 'w' || tolower (i->s[1]) != 'k') { dls_error (i, _("`WK' expected between week and year.")); - return 0; + return false; } i->s += 2; skip_whitespace (i); - return 1; + return true; } -static int +static bool parse_time_delimiter (struct data_in *i) { - int delim = 0; + bool delim = false; - while (have_char (i) - && (*i->s == ':' || *i->s == '.' || isspace (*i->s))) + while (have_char (i) && (*i->s == ':' || *i->s == '.' || isspace (*i->s))) { - delim = 1; + delim = true; i->s++; } if (delim) - return 1; + return true; dls_error (i, _("Delimiter expected between fields in time.")); - return 0; + return false; } -static int +static bool parse_hour (struct data_in *i, long *hour) { if (!parse_int (i, hour)) - return 0; + return false; if (*hour >= 0) - return 1; + return true; dls_error (i, _("Hour (%ld) must be positive."), *hour); - return 0; + return false; } -static int +static bool parse_minute (struct data_in *i, long *minute) { if (!parse_int (i, minute)) - return 0; + return false; if (*minute >= 0 && *minute <= 59) - return 1; + return true; dls_error (i, _("Minute (%ld) must be between 0 and 59."), *minute); - return 0; + return false; } -static int +static bool parse_opt_second (struct data_in *i, double *second) { - int delim = 0; + bool delim = false; char buf[64]; char *cp; @@ -1057,14 +986,14 @@ parse_opt_second (struct data_in *i, double *second) while (have_char (i) && (*i->s == ':' || *i->s == '.' || isspace (*i->s))) { - delim = 1; + delim = true; i->s++; } if (!delim || !isdigit (*i->s)) { *second = 0.0; - return 1; + return true; } cp = buf; @@ -1078,96 +1007,66 @@ parse_opt_second (struct data_in *i, double *second) *second = strtod (buf, NULL); - return 1; + return true; } -static int +static bool parse_hour24 (struct data_in *i, long *hour24) { if (!parse_int (i, hour24)) - return 0; + return false; if (*hour24 >= 0 && *hour24 <= 23) - return 1; + return true; dls_error (i, _("Hour (%ld) must be between 0 and 23."), *hour24); - return 0; + return false; } -static int -parse_weekday (struct data_in *i, int *weekday) +static bool +parse_weekday (struct data_in *i, long *weekday) { - /* PORTME */ - #define TUPLE(A,B) \ - (((A) << 8) + (B)) - - if (i->s + 1 >= i->e) - { - dls_error (i, _("Day of the week expected in date value.")); - return 0; - } - - switch (TUPLE (tolower (i->s[0]), tolower (i->s[1]))) + static const struct enum_name weekday_names[] = { - case TUPLE ('s', 'u'): - *weekday = 1; - break; - - case TUPLE ('m', 'o'): - *weekday = 2; - break; - - case TUPLE ('t', 'u'): - *weekday = 3; - break; - - case TUPLE ('w', 'e'): - *weekday = 4; - break; - - case TUPLE ('t', 'h'): - *weekday = 5; - break; - - case TUPLE ('f', 'r'): - *weekday = 6; - break; - - case TUPLE ('s', 'a'): - *weekday = 7; - break; - - default: - dls_error (i, _("Day of the week expected in date value.")); - return 0; - } - - while (have_char (i) && isalpha (*i->s)) - i->s++; - - return 1; + {"sunday", true, 1}, + {"su", true, 1}, + {"monday", true, 2}, + {"mo", true, 2}, + {"tuesday", true, 3}, + {"tu", true, 3}, + {"wednesday", true, 4}, + {"we", true, 4}, + {"thursday", true, 5}, + {"th", true, 5}, + {"friday", true, 6}, + {"fr", true, 6}, + {"saturday", true, 7}, + {"sa", true, 7}, + + {NULL, false, 0}, + }; - #undef TUPLE + return parse_enum (i, _("weekday"), weekday_names, weekday); } -static int +static bool parse_spaces (struct data_in *i) { skip_whitespace (i); - return 1; + return true; } -static int +static bool parse_sign (struct data_in *i, int *sign) { if (!force_have_char (i)) - return 0; + return false; switch (*i->s) { case '-': i->s++; - *sign = 1; + *sign = -1; break; case '+': @@ -1175,202 +1074,177 @@ parse_sign (struct data_in *i, int *sign) /* fall through */ default: - *sign = 0; + *sign = 1; break; } - return 1; + return true; } /* Date & time formats. */ -static int -valid_date (struct data_in *i) +static void +calendar_error (void *i_, const char *format, ...) +{ + struct data_in *i = i_; + va_list args; + + va_start (args, format); + vdls_error (i, format, args); + va_end (args); +} + +static bool +ymd_to_ofs (struct data_in *i, int year, int month, int day, double *ofs) { - if (i->v->f == SYSMIS) + *ofs = calendar_gregorian_to_offset (year, month, day, calendar_error, i); + return *ofs != SYSMIS; +} + +static bool +ymd_to_date (struct data_in *i, int year, int month, int day, double *date) +{ + if (ymd_to_ofs (i, year, month, day, date)) { - dls_error (i, _("Date is not in valid range between " - "15 Oct 1582 and 31 Dec 19999.")); - return 0; + *date *= 60. * 60. * 24.; + return true; } else - return 1; + return false; } -static int +static bool parse_DATE (struct data_in *i) { long day, month, year; - if (!parse_leader (i) - || !parse_day (i, &day) - || !parse_date_delimiter (i) - || !parse_month (i, &month) - || !parse_date_delimiter (i) - || !parse_year (i, &year) - || !parse_trailer (i)) - return 0; - - i->v->f = calendar_to_julian (year, month, day); - if (!valid_date (i)) - return 0; - i->v->f *= 60. * 60. * 24.; - - return 1; + return (parse_leader (i) + && parse_day (i, &day) + && parse_date_delimiter (i) + && parse_month (i, &month) + && parse_date_delimiter (i) + && parse_year (i, &year) + && parse_trailer (i) + && ymd_to_date (i, year, month, day, &i->v->f)); } -static int +static bool parse_ADATE (struct data_in *i) { long month, day, year; - if (!parse_leader (i) - || !parse_month (i, &month) - || !parse_date_delimiter (i) - || !parse_day (i, &day) - || !parse_date_delimiter (i) - || !parse_year (i, &year) - || !parse_trailer (i)) - return 0; - - i->v->f = calendar_to_julian (year, month, day); - if (!valid_date (i)) - return 0; - i->v->f *= 60. * 60. * 24.; - - return 1; + return (parse_leader (i) + && parse_month (i, &month) + && parse_date_delimiter (i) + && parse_day (i, &day) + && parse_date_delimiter (i) + && parse_year (i, &year) + && parse_trailer (i) + && ymd_to_date (i, year, month, day, &i->v->f)); } -static int +static bool parse_EDATE (struct data_in *i) { long month, day, year; - if (!parse_leader (i) - || !parse_day (i, &day) - || !parse_date_delimiter (i) - || !parse_month (i, &month) - || !parse_date_delimiter (i) - || !parse_year (i, &year) - || !parse_trailer (i)) - return 0; - - i->v->f = calendar_to_julian (year, month, day); - if (!valid_date (i)) - return 0; - i->v->f *= 60. * 60. * 24.; - - return 1; + return (parse_leader (i) + && parse_day (i, &day) + && parse_date_delimiter (i) + && parse_month (i, &month) + && parse_date_delimiter (i) + && parse_year (i, &year) + && parse_trailer (i) + && ymd_to_date (i, year, month, day, &i->v->f)); } -static int +static bool parse_SDATE (struct data_in *i) { long month, day, year; - if (!parse_leader (i) - || !parse_year (i, &year) - || !parse_date_delimiter (i) - || !parse_month (i, &month) - || !parse_date_delimiter (i) - || !parse_day (i, &day) - || !parse_trailer (i)) - return 0; - - i->v->f = calendar_to_julian (year, month, day); - if (!valid_date (i)) - return 0; - i->v->f *= 60. * 60. * 24.; - - return 1; + return (parse_leader (i) + && parse_year (i, &year) + && parse_date_delimiter (i) + && parse_month (i, &month) + && parse_date_delimiter (i) + && parse_day (i, &day) + && parse_trailer (i) + && ymd_to_date (i, year, month, day, &i->v->f)); } -static int +static bool parse_JDATE (struct data_in *i) { long julian; + double ofs; if (!parse_leader (i) || !parse_julian (i, &julian) - || !parse_trailer (i)) - return 0; - - if (julian / 1000 == 1582) - i->v->f = calendar_to_julian (1583, 1, 1) - 365; - else - i->v->f = calendar_to_julian (julian / 1000, 1, 1); + || !parse_trailer (i) + || !ymd_to_ofs (i, julian / 1000, 1, 1, &ofs)) + return false; - if (valid_date (i)) - { - i->v->f = (i->v->f + julian % 1000 - 1) * 60. * 60. * 24.; - if (i->v->f < 0.) - i->v->f = SYSMIS; - } - - return valid_date (i); + i->v->f = (ofs + julian % 1000 - 1) * 60. * 60. * 24.; + return true; } -static int +static bool parse_QYR (struct data_in *i) { long quarter, year; - if (!parse_leader (i) - || !parse_quarter (i, &quarter) - || !parse_q_delimiter (i) - || !parse_year (i, &year) - || !parse_trailer (i)) - return 0; - - i->v->f = calendar_to_julian (year, (quarter - 1) * 3 + 1, 1); - if (!valid_date (i)) - return 0; - i->v->f *= 60. * 60. * 24.; - - return 1; + return (parse_leader (i) + && parse_quarter (i, &quarter) + && parse_q_delimiter (i) + && parse_year (i, &year) + && parse_trailer (i) + && ymd_to_date (i, year, (quarter - 1) * 3 + 1, 1, &i->v->f)); } -static int +static bool parse_MOYR (struct data_in *i) { long month, year; - if (!parse_leader (i) - || !parse_month (i, &month) - || !parse_date_delimiter (i) - || !parse_year (i, &year) - || !parse_trailer (i)) - return 0; - - i->v->f = calendar_to_julian (year, month, 1); - if (!valid_date (i)) - return 0; - i->v->f *= 60. * 60. * 24.; - - return 1; + return (parse_leader (i) + && parse_month (i, &month) + && parse_date_delimiter (i) + && parse_year (i, &year) + && parse_trailer (i) + && ymd_to_date (i, year, month, 1, &i->v->f)); } -static int +static bool parse_WKYR (struct data_in *i) { long week, year; + double ofs; if (!parse_leader (i) || !parse_week (i, &week) || !parse_wk_delimiter (i) || !parse_year (i, &year) || !parse_trailer (i)) - return 0; + return false; - i->v->f = calendar_to_julian (year, 1, 1); - if (!valid_date (i)) - return 0; - i->v->f = (i->v->f + (week - 1) * 7) * 60. * 60. * 24.; + if (year != 1582) + { + if (!ymd_to_ofs (i, year, 1, 1, &ofs)) + return false; + } + else + { + if (ymd_to_ofs (i, 1583, 1, 1, &ofs)) + return false; + ofs -= 365; + } - return 1; + i->v->f = (ofs + (week - 1) * 7) * 60. * 60. * 24.; + return true; } -static int +static bool parse_TIME (struct data_in *i) { int sign; @@ -1384,15 +1258,13 @@ parse_TIME (struct data_in *i) || !parse_time_delimiter (i) || !parse_minute (i, &minute) || !parse_opt_second (i, &second)) - return 0; + return false; - i->v->f = hour * 60. * 60. + minute * 60. + second; - if (sign) - i->v->f = -i->v->f; - return 1; + i->v->f = (hour * 60. * 60. + minute * 60. + second) * sign; + return true; } -static int +static bool parse_DTIME (struct data_in *i) { int sign; @@ -1409,18 +1281,16 @@ parse_DTIME (struct data_in *i) || !parse_time_delimiter (i) || !parse_minute (i, &minute) || !parse_opt_second (i, &second)) - return 0; + return false; i->v->f = (day_count * 60. * 60. * 24. + hour * 60. * 60. + minute * 60. - + second); - if (sign) - i->v->f = -i->v->f; - return 1; + + second) * sign; + return true; } -static int +static bool parse_DATETIME (struct data_in *i) { long day, month, year; @@ -1438,35 +1308,29 @@ parse_DATETIME (struct data_in *i) || !parse_hour24 (i, &hour24) || !parse_time_delimiter (i) || !parse_minute (i, &minute) - || !parse_opt_second (i, &second)) - return 0; - - i->v->f = calendar_to_julian (year, month, day); - if (!valid_date (i)) - return 0; - i->v->f = (i->v->f * 60. * 60. * 24. - + hour24 * 60. * 60. - + minute * 60. - + second); + || !parse_opt_second (i, &second) + || !ymd_to_date (i, year, month, day, &i->v->f)) + return false; - return 1; + i->v->f += hour24 * 60. * 60. + minute * 60. + second; + return true; } -static int +static bool parse_WKDAY (struct data_in *i) { - int weekday; + long weekday; if (!parse_leader (i) || !parse_weekday (i, &weekday) || !parse_trailer (i)) - return 0; + return false; i->v->f = weekday; - return 1; + return true; } -static int +static bool parse_MONTH (struct data_in *i) { long month; @@ -1474,10 +1338,10 @@ parse_MONTH (struct data_in *i) if (!parse_leader (i) || !parse_month (i, &month) || !parse_trailer (i)) - return 0; + return false; i->v->f = month; - return 1; + return true; } /* Main dispatcher. */ @@ -1494,7 +1358,7 @@ default_result (struct data_in *i) i->v->f = get_blanks(); } -int +bool data_in (struct data_in *i) { const struct fmt_desc *const fmt = &formats[i->format.type]; @@ -1503,7 +1367,7 @@ data_in (struct data_in *i) if (i->e == i->s || i->format.w <= 0) { default_result (i); - return 1; + return true; } i->f2 = i->f1 + (i->e - i->s) - 1; @@ -1530,13 +1394,13 @@ data_in (struct data_in *i) if (++cp == i->e) { i->v->f = get_blanks(); - return 1; + return true; } } } { - static int (*const handlers[FMT_NUMBER_OF_FORMATS])(struct data_in *) = + static bool (*const handlers[FMT_NUMBER_OF_FORMATS])(struct data_in *) = { parse_numeric, parse_N, parse_numeric, parse_numeric, parse_numeric, parse_numeric, parse_numeric, @@ -1549,8 +1413,8 @@ data_in (struct data_in *i) parse_WKDAY, parse_MONTH, }; - int (*handler)(struct data_in *); - int success; + bool (*handler)(struct data_in *); + bool success; handler = handlers[i->format.type]; assert (handler != NULL);