X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fexpressions%2Fparse.c;h=a7064e034c8728b05e3b1264367e7a8075379fe0;hb=c434e369b6695f8135a2914e9a425edcdd09ef35;hp=ea3b06a5dbd18ce5fa8394aad8d1c83c2801e9a3;hpb=e1ca4ab566c6f8317ba8ff0fd27046b82b4acd63;p=pspp-builds.git diff --git a/src/expressions/parse.c b/src/expressions/parse.c index ea3b06a5..a7064e03 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" @@ -56,6 +56,8 @@ static struct expression *finish_expression (union any_node *, struct expression *); static bool type_check (struct expression *, union any_node **, enum expr_type expected_type); +static union any_node *allocate_unary_variable (struct expression *, + struct variable *); /* Public functions. */ @@ -267,13 +269,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 @@ -335,7 +336,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; @@ -345,7 +347,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; @@ -387,10 +390,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; } @@ -402,7 +408,7 @@ type_coercion (struct expression *e, atom_type required_type, union any_node **node, const char *operator_name) { - return type_coercion_core (e, required_type, node, operator_name, 1); + return type_coercion_core (e, required_type, node, operator_name, true); } /* Coerces *NODE to type REQUIRED_TYPE. @@ -411,7 +417,7 @@ static void type_coercion_assert (struct expression *e, atom_type required_type, union any_node **node) { - int success = type_coercion_core (e, required_type, node, NULL, 1); + int success = type_coercion_core (e, required_type, node, NULL, true); assert (success); } @@ -421,7 +427,7 @@ static bool is_coercible (atom_type required_type, union any_node *const *node) { return type_coercion_core (NULL, required_type, - (union any_node **) node, NULL, 0); + (union any_node **) node, NULL, false); } /* How to parse an operator. */ @@ -517,7 +523,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. */ @@ -651,7 +657,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), @@ -783,12 +789,7 @@ parse_primary (struct expression *e) /* It looks like a user variable. (It could be a format specifier, but we'll assume it's a variable unless proven otherwise. */ - struct variable *v = parse_dict_variable (e->dict); - assert (v != NULL); - return expr_allocate_unary (e, - (v->type == NUMERIC - ? OP_NUM_VAR : OP_STR_VAR), - expr_allocate_variable (e, v)); + return allocate_unary_variable (e, parse_dict_variable (e->dict)); } else { @@ -803,7 +804,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 (); @@ -863,7 +865,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. */ @@ -879,14 +881,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; } @@ -915,6 +917,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), @@ -945,7 +953,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)); } @@ -1098,14 +1106,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, '.'); @@ -1159,7 +1165,7 @@ parse_function (struct expression *e) goto fail; for (i = 0; i < var_cnt; i++) add_arg (&args, &arg_cnt, &arg_cap, - expr_allocate_variable (e, vars[i])); + allocate_unary_variable (e, vars[i])); free (vars); } else @@ -1204,13 +1210,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; } @@ -1268,7 +1279,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); } @@ -1422,3 +1433,13 @@ expr_allocate_format (struct expression *e, const struct fmt_spec *format) n->format.f = *format; return n; } + +/* Allocates a unary composite node that represents the value of + variable V in expression E. */ +static union any_node * +allocate_unary_variable (struct expression *e, struct variable *v) +{ + assert (v != NULL); + return expr_allocate_unary (e, v->type == NUMERIC ? OP_NUM_VAR : OP_STR_VAR, + expr_allocate_variable (e, v)); +}