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 <config.h>
-#include <assert.h>
+#include "data-in.h"
+#include "error.h"
#include <math.h>
#include <ctype.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
-#include "data-in.h"
+#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"
#include "str.h"
#include "var.h"
\f
-#undef DEBUGGING
-/*#define DEBUGGING 1 */
#include "debug-print.h"
\f
/* Specialized error routine. */
static void dls_error (const struct data_in *, const char *format, ...)
- __attribute__ ((format (printf, 2, 3)));
+ 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 (NULL, &title, 64);
- if (!getl_reading_script)
- ds_concat (&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_value (&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);
+}
+\f
+/* Parsing utility functions. */
+
/* Excludes leading and trailing whitespace from I by adjusting
pointers. */
static void
/* 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);
+}
\f
/* 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. */
if (*i->s == '-' || *i->s == '+')
i->s++;
}
+ else
+ sign = 1;
if (type != FMT_DOT)
{
- decimal = set_decimal;
- grouping = set_grouping;
+ decimal = get_decimal();
+ grouping = get_grouping();
}
else
{
- decimal = set_grouping;
- grouping = set_decimal;
+ decimal = get_grouping();
+ grouping = get_decimal();
}
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)
}
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)
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 == '%')
{
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. */
return cp - s;
}
-static inline int
+static inline bool
parse_N (struct data_in *i)
{
const unsigned char *cp;
+ i->v->f = 0;
for (cp = i->s; cp < i->e; cp++)
{
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;
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. */
if ((i->e - i->s) % 2)
{
dls_error (i, _("Field must have even length."));
- return 0;
+ return false;
}
{
if (!isxdigit (*cp))
{
dls_error (i, _("Field must contain only hex digits."));
- return 0;
+ return false;
}
}
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)
{
- msg (MW, _("Quality of zoned decimal (Z) input format code is "
- "suspect. Check your results three times, report bugs "
- "to author."));
- warned = 1;
+ msg (MW,
+ _("Quality of zoned decimal (Z) input format code is "
+ "suspect. Check your results three times. Report bugs "
+ "to %s."),PACKAGE_BUGREPORT);
+ warned = true;
}
}
{
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 ? '-' : '+';
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';
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];
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;
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;
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;
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
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;
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. */
if ((i->e - i->s) % 2)
{
dls_error (i, _("Field must have even length."));
- return 0;
+ return false;
}
{
if (!isxdigit (*cp))
{
dls_error (i, _("Field must contain only hex digits."));
- return 0;
+ return false;
}
}
memset (i->v->s + (i->e - i->s) / 2, ' ', (i->format.w - (i->e - i->s)) / 2);
}
- return 1;
+ return true;
}
\f
/* Date & time format components. */
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 == '+')
{
}
else if (*i->s == '-')
{
- negative = 1;
+ negative = true;
i->s++;
force_have_char (i);
}
if (!isdigit (*i->s))
{
dls_error (i, _("Digit expected in field."));
- return 0;
+ return false;
}
*result = 0;
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;
+ return false;
}
-
- 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;
- }
-
- {
- 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;
if (day < 1 || day > 366)
{
dls_error (i, _("Julian day (%d) must be between 1 and 366."), day);
- return 0;
+ return false;
}
}
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);
|| 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;
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;
*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)
+ static const struct enum_name weekday_names[] =
{
- dls_error (i, _("Day of the week expected in date value."));
- return 0;
- }
-
- switch (TUPLE (tolower (i->s[0]), tolower (i->s[1])))
- {
- 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 '+':
/* fall through */
default:
- *sign = 0;
+ *sign = 1;
break;
}
- return 1;
+ return true;
}
\f
/* 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)
+{
+ *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 (i->v->f == SYSMIS)
+ 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);
-
- 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;
- }
+ || !parse_trailer (i)
+ || !ymd_to_ofs (i, julian / 1000, 1, 1, &ofs))
+ return false;
- 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;
|| !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;
|| !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;
|| !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;
if (!parse_leader (i)
|| !parse_month (i, &month)
|| !parse_trailer (i))
- return 0;
+ return false;
i->v->f = month;
- return 1;
+ return true;
}
\f
/* Main dispatcher. */
if (fmt->cat & FCAT_STRING)
memset (i->v->s, ' ', i->format.w);
else
- i->v->f = set_blanks;
+ i->v->f = get_blanks();
}
-int
+bool
data_in (struct data_in *i)
{
const struct fmt_desc *const fmt = &formats[i->format.type];
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;
if (++cp == i->e)
{
- i->v->f = set_blanks;
- return 1;
+ i->v->f = get_blanks();
+ 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,
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);