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 "private.h"
}
}
+/* Parses and returns an expression of the given TYPE, as
+ expr_parse(), and sets up so that destroying POOL will free
+ the expression as well. */
+struct expression *
+expr_parse_pool (struct pool *pool,
+ struct dictionary *dict, enum expr_type type)
+{
+ struct expression *e = expr_parse (dict, type);
+ if (e != NULL)
+ pool_add_subpool (pool, e->expr_pool);
+ return e;
+}
+
/* Free expression E. */
void
expr_free (struct expression *e)
/* Considers whether *NODE may be coerced to type REQUIRED_TYPE.
Returns true if possible, false if disallowed.
- If DO_COERCION is zero, then *NODE is not modified and there
+ If DO_COERCION is false, then *NODE is not modified and there
are no side effects.
- Otherwise, DO_COERCION is nonzero. In this case, we perform
- the coercion if possible, possibly modifying *NODE. If the
- coercion is not possible then we free *NODE and set *NODE to
- a null pointer.
+ If DO_COERCION is true, we perform the coercion if possible,
+ modifying *NODE if necessary. If the coercion is not possible
+ then we free *NODE and set *NODE to a null pointer.
This function's interface is somewhat awkward. Use one of the
wrapper functions type_coercion(), type_coercion_assert(), or
case OP_ni_format:
if ((*node)->type == OP_format
- && check_input_specifier (&(*node)->format.f, 0))
+ && check_input_specifier (&(*node)->format.f, false)
+ && check_specifier_type (&(*node)->format.f, NUMERIC, false))
{
if (do_coercion)
(*node)->type = OP_ni_format;
case OP_no_format:
if ((*node)->type == OP_format
- && check_output_specifier (&(*node)->format.f, 0))
+ && check_output_specifier (&(*node)->format.f, false)
+ && check_specifier_type (&(*node)->format.f, NUMERIC, false))
{
if (do_coercion)
(*node)->type = OP_no_format;
}
if (do_coercion)
- msg (SE, _("Type mismatch while applying %s operator: "
- "cannot convert %s to %s."),
- operator_name,
- atom_type_name (actual_type), atom_type_name (required_type));
+ {
+ msg (SE, _("Type mismatch while applying %s operator: "
+ "cannot convert %s to %s."),
+ operator_name,
+ atom_type_name (actual_type), atom_type_name (required_type));
+ *node = NULL;
+ }
return false;
}
/* Convert the left-hand side to type OPERAND_TYPE. */
if (!type_coercion (e, operand_type, &node, operator->name))
- return node;
+ return NULL;
/* Parse the right-hand side and coerce to type
OPERAND_TYPE. */
static const struct operator ops[] =
{
{ '+', OP_ADD, "addition (\"+\")" },
- { '-', OP_SUB, "subtraction (\"-\")-" },
+ { '-', OP_SUB, "subtraction (\"-\")" },
};
return parse_binary_operators (e, parse_mul (e),
"JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
};
+ time_t last_vfm_invocation = vfm_last_invocation ();
struct tm *time;
char temp_buf[10];
return expr_allocate_number (e, SYSMIS);
else if (lex_match_id ("$JDATE"))
{
- struct tm *time = localtime (&last_vfm_invocation);
- return expr_allocate_number (e, expr_ymd_to_ofs (time->tm_year + 1900,
- time->tm_mon + 1,
- time->tm_mday));
+ time_t time = vfm_last_invocation ();
+ struct tm *tm = localtime (&time);
+ return expr_allocate_number (e, expr_ymd_to_ofs (tm->tm_year + 1900,
+ tm->tm_mon + 1,
+ tm->tm_mday));
}
else if (lex_match_id ("$TIME"))
{
- struct tm *time = localtime (&last_vfm_invocation);
+ time_t time = vfm_last_invocation ();
+ struct tm *tm = localtime (&time);
return expr_allocate_number (e,
- expr_ymd_to_date (time->tm_year + 1900,
- time->tm_mon + 1,
- time->tm_mday)
- + time->tm_hour * 60 * 60.
- + time->tm_min * 60.
- + time->tm_sec);
+ expr_ymd_to_date (tm->tm_year + 1900,
+ tm->tm_mon + 1,
+ tm->tm_mday)
+ + tm->tm_hour * 60 * 60.
+ + tm->tm_min * 60.
+ + tm->tm_sec);
}
else if (lex_match_id ("$LENGTH"))
return expr_allocate_number (e, get_viewlength ());
}
break;
- case T_NUM:
+ case T_POS_NUM:
+ case T_NEG_NUM:
{
union any_node *node = expr_allocate_number (e, tokval);
lex_get ();
return expr_allocate_binary (e, (vector->var[0]->type == NUMERIC
? OP_VEC_ELEM_NUM : OP_VEC_ELEM_STR),
- expr_allocate_vector (e, vector), element);
+ element, expr_allocate_vector (e, vector));
}
\f
/* Individual function parsing. */
size_t name_len = strcspn (*name, ".");
if (test_len == name_len)
{
- if (memcmp (*test, *name, test_len))
+ if (buf_compare_case (*test, *name, test_len))
return false;
}
else if (test_len < 3 || test_len > name_len)
return false;
else
{
- if (memcmp (*test, *name, test_len))
+ if (buf_compare_case (*test, *name, test_len))
return false;
}
}
}
+static int
+compare_strings (const char *test, const char *name)
+{
+ return strcasecmp (test, name);
+}
+
static bool
lookup_function_helper (const char *name,
int (*compare) (const char *test, const char *name),
const struct operation **last)
{
*first = *last = NULL;
- return (lookup_function_helper (name, strcmp, first, last)
+ return (lookup_function_helper (name, compare_strings, first, last)
|| lookup_function_helper (name, compare_names, first, last));
}
{
assert ((f->flags & OPF_MIN_VALID) == 0);
msg (SE, _("%s function does not accept a minimum valid "
- "argument count."));
+ "argument count."), f->prototype);
return false;
}
else
if (array_arg_cnt < f->array_min_elems)
{
msg (SE, _("%s requires at least %d valid arguments in list."),
- f->prototype);
+ f->prototype, f->array_min_elems);
return false;
}
else if (min_valid > array_arg_cnt)
}
else
{
- ds_create (&s, _("Function invocation "));
+ ds_puts (&s, _("Function invocation "));
put_invocation (&s, func_name, args, arg_cnt);
ds_puts (&s, _(" does not match any known function. Candidates are:"));
for (f = first; f < last; f++)
- {
- ds_printf (&s, "\n%s", f->prototype);
- }
+ ds_printf (&s, "\n%s", f->prototype);
}
ds_putc (&s, '.');
if (token == T_ID && lex_look_ahead () == 'T')
{
struct variable **vars;
- int var_cnt;
- int i;
+ size_t var_cnt;
+ size_t i;
if (!parse_variables (default_dict, &vars, &var_cnt, PV_SINGLE))
goto fail;
n = expr_allocate_composite (e, f - operations, args, arg_cnt);
n->composite.min_valid = min_valid != -1 ? min_valid : f->array_min_elems;
- if (n->type == OP_LAG_Vnn || n->type == OP_LAG_Vsn)
+ if (n->type == OP_LAG_Vn || n->type == OP_LAG_Vs)
+ {
+ if (n_lag < 1)
+ n_lag = 1;
+ }
+ else if (n->type == OP_LAG_Vnn || n->type == OP_LAG_Vsn)
{
int n_before;
assert (n->composite.arg_cnt == 2);
assert (n->composite.args[1]->type == OP_pos_int);
n_before = n->composite.args[1]->integer.i;
- if (n_before > n_lag)
+ if (n_lag < n_before)
n_lag = n_before;
}
union any_node *
expr_allocate_unary (struct expression *e, operation_type op,
-union any_node *arg0)
+ union any_node *arg0)
{
return expr_allocate_composite (e, op, &arg0, 1);
}