X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fexpressions%2Fparse.c;h=fcfd8ef3fb44a7d36ccc028f381feb53766b155f;hb=53ceff2865473a6b561b521986fafd31a993a1a6;hp=b1998f63c8f89daa5ea41456ad4c0bba80659de9;hpb=e32e05bf60402d3229e45adcc9b4c8d5bb27d174;p=pspp diff --git a/src/expressions/parse.c b/src/expressions/parse.c index b1998f63c8..fcfd8ef3fb 100644 --- a/src/expressions/parse.c +++ b/src/expressions/parse.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 "private.h" @@ -86,6 +86,19 @@ expr_parse (struct dictionary *dict, enum expr_type type) } } +/* 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) @@ -269,13 +282,12 @@ type_check (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 @@ -337,7 +349,8 @@ type_coercion_core (struct expression *e, 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; @@ -347,7 +360,8 @@ type_coercion_core (struct expression *e, 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; @@ -389,10 +403,13 @@ type_coercion_core (struct expression *e, } 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; } @@ -519,7 +536,7 @@ parse_binary_operators (struct expression *e, union any_node *node, /* 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. */ @@ -653,7 +670,7 @@ parse_add (struct expression *e) static const struct operator ops[] = { { '+', OP_ADD, "addition (\"+\")" }, - { '-', OP_SUB, "subtraction (\"-\")-" }, + { '-', OP_SUB, "subtraction (\"-\")" }, }; return parse_binary_operators (e, parse_mul (e), @@ -714,6 +731,7 @@ parse_sysvar (struct expression *e) "JUL", "AUG", "SEP", "OCT", "NOV", "DEC", }; + time_t last_vfm_invocation = vfm_last_invocation (); struct tm *time; char temp_buf[10]; @@ -731,21 +749,23 @@ parse_sysvar (struct expression *e) 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 ()); @@ -800,7 +820,8 @@ parse_primary (struct expression *e) } break; - case T_NUM: + case T_POS_NUM: + case T_NEG_NUM: { union any_node *node = expr_allocate_number (e, tokval); lex_get (); @@ -860,7 +881,7 @@ parse_vector_element (struct expression *e) 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)); } /* Individual function parsing. */ @@ -876,14 +897,14 @@ word_matches (const char **test, const char **name) 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; } @@ -912,6 +933,12 @@ compare_names (const char *test, const char *name) } } +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), @@ -942,7 +969,7 @@ lookup_function (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)); } @@ -1022,7 +1049,7 @@ validate_function_args (const struct operation *f, int arg_cnt, int min_valid) { 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 @@ -1031,7 +1058,7 @@ validate_function_args (const struct operation *f, int arg_cnt, int min_valid) 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) @@ -1095,14 +1122,12 @@ no_match (const char *func_name, } 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, '.'); @@ -1149,8 +1174,8 @@ parse_function (struct expression *e) 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; @@ -1201,13 +1226,18 @@ parse_function (struct expression *e) 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; } @@ -1265,7 +1295,7 @@ expr_allocate_nullary (struct expression *e, operation_type op) 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); }