// Time construction & extraction functions.
function TIME.HMS (h, m, s)
+ expression e;
+ expr_node n;
{
if ((h > 0. || m > 0. || s > 0.) && (h < 0. || m < 0. || s < 0.))
{
- msg (SW, _("TIME.HMS cannot mix positive and negative arguments."));
+ msg_at (SW, expr_location (e, n),
+ _("TIME.HMS cannot accept a mix of positive and negative "
+ "arguments."));
+ double args[] = { h, m, s };
+ for (size_t i = 0; i < 3; i++)
+ if (args[i] > 0)
+ msg_at (SN, expr_location (e, n->args[i]),
+ _("This argument has positive value %g."), args[i]);
+ else if (args[i] < 0)
+ msg_at (SN, expr_location (e, n->args[i]),
+ _("This argument has negative value %g."), args[i]);
return SYSMIS;
}
else
function CTIME.SECONDS (time) = time;
// Date construction functions.
-function DATE.DMY (d, m, y) = expr_ymd_to_date (y, m, d);
-function DATE.MDY (m, d, y) = expr_ymd_to_date (y, m, d);
-function DATE.MOYR (m, y) = expr_ymd_to_date (y, m, 1);
-function DATE.QYR (q, y)
+function DATE.DMY (integer d, integer m, integer y)
+ expression e;
+ expr_node n;
+= expr_ymd_to_date (y, m, d, e, n, 3, 2, 1);
+
+function DATE.MDY (integer m, integer d, integer y)
+ expression e;
+ expr_node n;
+= expr_ymd_to_date (y, m, d, e, n, 3, 1, 2);
+
+function DATE.MOYR (integer m, integer y)
+ expression e;
+ expr_node n;
+= expr_ymd_to_date (y, m, 1, e, n, 2, 1, 0);
+
+function DATE.QYR (integer q, integer y)
+ expression e;
+ expr_node n;
{
- if (q < 1.0 || q > 4.0 || q != (int) q)
+ if (q < 1 || q > 4)
{
- msg (SW, _("The first argument to DATE.QYR must be 1, 2, 3, or 4."));
+ msg_at (SW, expr_location (e, n->args[0]),
+ _("Argument 1 to DATE.QYR must be 1, 2, 3, or 4 (not %d)."), q);
return SYSMIS;
}
- return expr_ymd_to_date (y, q * 3 - 2, 1);
+ return expr_ymd_to_date (y, q * 3 - 2, 1, e, n, 2, 0, 0);
+}
+
+function DATE.WKYR (integer w, integer y)
+ expression e;
+ expr_node n;
+{
+ if (w < 1 || w > 53)
+ {
+ msg_at (SE, expr_location (e, n->args[0]),
+ _("The week argument to DATE.WKYR is outside the acceptable "
+ "range of 1 to 53. The result will be system-missing."));
+ return SYSMIS;
+ }
+ else
+ {
+ double yr_1_1 = expr_ymd_to_ofs (y, 1, 1, e, n, 2, 0, 0);
+ if (yr_1_1 != SYSMIS)
+ return DAY_S * (yr_1_1 + WEEK_DAY * (w - 1));
+ else
+ return SYSMIS;
+ }
+}
+
+function DATE.YRDAY (integer y, integer yd)
+ expression e;
+ expr_node n;
+{
+ if (yd < 1 || yd > 366)
+ {
+ msg_at (SE, expr_location (e, n->args[1]),
+ _("DATE.YRDAY day argument %d is outside the acceptable "
+ "range of 1 to 366. The result will be system-missing."), yd);
+ return SYSMIS;
+ }
+ else
+ {
+ double yr_1_1 = expr_ymd_to_ofs (y, 1, 1, e, n, 1, 0, 0);
+ if (yr_1_1 != SYSMIS)
+ return DAY_S * (yr_1_1 + yd - 1.);
+ else
+ return SYSMIS;
+ }
+}
+
+function YRMODA (integer y, integer m, integer d)
+ expression e;
+ expr_node n;
+{
+ if (y >= 0 && y <= 99)
+ y += 1900;
+ else if (y > 47516)
+ {
+ msg_at (SE, expr_location (e, n->args[0]),
+ _("The year argument to YRMODA is greater than 47516. "
+ "The result will be system-missing."));
+ return SYSMIS;
+ }
+
+ return expr_ymd_to_ofs (y, m, d, e, n, 1, 2, 3);
}
-function DATE.WKYR (w, y) = expr_wkyr_to_date (w, y);
-function DATE.YRDAY (y, yday) = expr_yrday_to_date (y, yday);
-function YRMODA (y, m, d) = expr_yrmoda (y, m, d);
// Date extraction functions.
function XDATE.TDAY (date) = floor (date / DAY_S);
// Date arithmetic functions.
no_abbrev function DATEDIFF (date2 >= DAY_S, date1 >= DAY_S, string unit)
- = expr_date_difference (date1, date2, unit);
+ expression e;
+ expr_node n;
+= expr_date_difference (date1, date2, unit, e, n);
+
no_abbrev function DATESUM (date, quantity, string unit)
- = expr_date_sum (date, quantity, unit, ss_cstr ("closest"));
+ expression e;
+ expr_node n;
+= expr_date_sum_closest (date, quantity, unit, e, n);
no_abbrev function DATESUM (date, quantity, string unit, string method)
- = expr_date_sum (date, quantity, unit, method);
+ expression e;
+ expr_node n;
+= expr_date_sum (date, quantity, unit, method, e, n);
// String functions.
}
function NUMBER (string s, ni_format f)
+ expression e;
+ expr_node n;
{
union value out;
char *error;
settings_get_fmt_settings (), &out);
else
{
- msg (SE, "Cannot parse `%.*s' as format %s: %s",
- (int) s.length, s.string, fmt_name (f->type), error);
+ msg_at (SE, expr_location (e, n->args[0]),
+ _("Cannot parse `%.*s' as format %s: %s"),
+ (int) s.length, s.string, fmt_name (f->type), error);
free (error);
}
return out.f;
// Artificial.
operator SQUARE (x) = x * x;
-boolean operator NUM_TO_BOOLEAN (x)
+absorb_miss boolean operator NUM_TO_BOOLEAN (x)
+ expression e;
+ expr_node n;
{
if (x == 0. || x == 1. || x == SYSMIS)
return x;
- msg (SE, _("A logical expression was found to have a value other than 0 "
- "(false), 1 (true), or the system-missing value. The result "
- "was forced to 0."));
+ msg_at (SE, expr_location (e, n),
+ _("This logical expression must evaluate to 0 or 1. "
+ "Treating unexpected value %g as 0."), x);
return 0.;
}
+operator NUM_TO_INTEGER (x)
+ expression e;
+ expr_node n;
+{
+ if (x == floor (x) && x > INT_MIN && x <= INT_MAX)
+ return x;
+
+ msg_at (SE, expr_location (e, n),
+ _("Treating unexpected non-integer value %g as missing."), x);
+ return SYSMIS;
+}
+
operator BOOLEAN_TO_NUM (boolean x) = x;
// Beta distribution.
no_opt operator VEC_ELEM_NUM (idx)
vector v;
case c;
+ expression e;
+ expr_node n;
{
if (idx >= 1 && idx <= vector_get_n_vars (v))
{
else
{
if (idx == SYSMIS)
- msg (SE, _("SYSMIS is not a valid index value for vector "
+ msg_at (SE, expr_location (e, n->args[0]),
+ _("SYSMIS is not a valid index value for %zu-element vector "
"%s. The result will be set to SYSMIS."),
- vector_get_name (v));
+ vector_get_n_vars (v), vector_get_name (v));
else
- msg (SE, _("%g is not a valid index value for vector %s. "
- "The result will be set to SYSMIS."),
- idx, vector_get_name (v));
+ msg_at (SE, expr_location (e, n->args[0]),
+ _("%g is not a valid index value for %zu-element vector %s. "
+ "The result will be set to SYSMIS."),
+ idx, vector_get_n_vars (v), vector_get_name (v));
return SYSMIS;
}
}
expression e;
vector v;
case c;
+ expr_node n;
{
if (idx >= 1 && idx <= vector_get_n_vars (v))
{
else
{
if (idx == SYSMIS)
- msg (SE, _("SYSMIS is not a valid index value for vector "
+ msg_at (SE, expr_location (e, n->args[0]),
+ _("SYSMIS is not a valid index value for %zu-element vector "
"%s. The result will be set to the empty string."),
- vector_get_name (v));
+ vector_get_n_vars (v), vector_get_name (v));
else
- msg (SE, _("%g is not a valid index value for vector %s. "
- "The result will be set to the empty string."),
- idx, vector_get_name (v));
+ msg_at (SE, expr_location (e, n->args[0]),
+ _("%g is not a valid index value for %zu-element vector %s. "
+ "The result will be set to the empty string."),
+ idx, vector_get_n_vars (v), vector_get_name (v));
return empty_string;
}
}