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 "error.h"
#include "str.h"
#include "var.h"
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
struct compute_trns;
struct lvalue;
vector element. */
static struct lvalue *lvalue_parse (void);
static int lvalue_get_type (const struct lvalue *);
-static int lvalue_is_vector (const struct lvalue *);
+static bool lvalue_is_vector (const struct lvalue *);
static void lvalue_finalize (struct lvalue *,
struct compute_trns *);
static void lvalue_destroy (struct lvalue *);
/* COMPUTE and IF transformation. */
struct compute_trns
{
- struct trns_header h;
-
/* Test expression (IF only). */
struct expression *test; /* Test expression. */
struct expression *rvalue; /* Rvalue expression. */
};
-static int parse_rvalue_expression (struct compute_trns *,
- const struct lvalue *);
+static struct expression *parse_rvalue (const struct lvalue *);
static struct compute_trns *compute_trns_create (void);
-static void compute_trns_free (struct trns_header *);
+static trns_proc_func *get_proc_func (const struct lvalue *);
+static trns_free_func compute_trns_free;
\f
/* COMPUTE. */
struct lvalue *lvalue = NULL;
struct compute_trns *compute = NULL;
+ compute = compute_trns_create ();
+
lvalue = lvalue_parse ();
if (lvalue == NULL)
goto fail;
- compute = compute_trns_create ();
-
- if (!lex_force_match ('=') || !parse_rvalue_expression (compute, lvalue))
+ if (!lex_force_match ('='))
+ goto fail;
+ compute->rvalue = parse_rvalue (lvalue);
+ if (compute->rvalue == NULL)
goto fail;
- lvalue_finalize (lvalue, compute);
+ add_transformation (get_proc_func (lvalue), compute_trns_free, compute);
- add_transformation (&compute->h);
+ lvalue_finalize (lvalue, compute);
- return CMD_SUCCESS;
+ return lex_end_of_command ();
fail:
lvalue_destroy (lvalue);
- if (compute != NULL)
- {
- compute_trns_free (&compute->h);
- free (compute);
- }
+ compute_trns_free (compute);
return CMD_FAILURE;
}
\f
/* Handle COMPUTE or IF with numeric target variable. */
static int
-compute_num (struct trns_header *compute_, struct ccase *c,
- int case_num)
+compute_num (void *compute_, struct ccase *c, int case_num)
{
- struct compute_trns *compute = (struct compute_trns *) compute_;
+ struct compute_trns *compute = compute_;
if (compute->test == NULL
|| expr_evaluate_num (compute->test, c, case_num) == 1.0)
/* Handle COMPUTE or IF with numeric vector element target
variable. */
static int
-compute_num_vec (struct trns_header *compute_, struct ccase *c,
- int case_num)
+compute_num_vec (void *compute_, struct ccase *c, int case_num)
{
- struct compute_trns *compute = (struct compute_trns *) compute_;
+ struct compute_trns *compute = compute_;
if (compute->test == NULL
|| expr_evaluate_num (compute->test, c, case_num) == 1.0)
/* Handle COMPUTE or IF with string target variable. */
static int
-compute_str (struct trns_header *compute_, struct ccase *c,
- int case_num)
+compute_str (void *compute_, struct ccase *c, int case_num)
{
- struct compute_trns *compute = (struct compute_trns *) compute_;
+ struct compute_trns *compute = compute_;
if (compute->test == NULL
|| expr_evaluate_num (compute->test, c, case_num) == 1.0)
/* Handle COMPUTE or IF with string vector element target
variable. */
static int
-compute_str_vec (struct trns_header *compute_, struct ccase *c,
- int case_num)
+compute_str_vec (void *compute_, struct ccase *c, int case_num)
{
- struct compute_trns *compute = (struct compute_trns *) compute_;
+ struct compute_trns *compute = compute_;
if (compute->test == NULL
|| expr_evaluate_num (compute->test, c, case_num) == 1.0)
goto fail;
/* Rvalue expression. */
- if (!lex_force_match ('=') || !parse_rvalue_expression (compute, lvalue))
+ if (!lex_force_match ('='))
+ goto fail;
+ compute->rvalue = parse_rvalue (lvalue);
+ if (compute->rvalue == NULL)
goto fail;
- lvalue_finalize (lvalue, compute);
+ add_transformation (get_proc_func (lvalue), compute_trns_free, compute);
- add_transformation (&compute->h);
+ lvalue_finalize (lvalue, compute);
- return CMD_SUCCESS;
+ return lex_end_of_command ();
fail:
lvalue_destroy (lvalue);
- if (compute != NULL)
- {
- compute_trns_free (&compute->h);
- free (compute);
- }
+ compute_trns_free (compute);
return CMD_FAILURE;
}
\f
/* Code common to COMPUTE and IF. */
-/* Checks for type mismatches on transformation C. Also checks for
- command terminator, sets the case-handling proc from the array
- passed. */
-static int
-parse_rvalue_expression (struct compute_trns *compute,
- const struct lvalue *lvalue)
+static trns_proc_func *
+get_proc_func (const struct lvalue *lvalue)
{
- int type = lvalue_get_type (lvalue);
- int vector = lvalue_is_vector (lvalue);
+ bool is_numeric = lvalue_get_type (lvalue) == NUMERIC;
+ bool is_vector = lvalue_is_vector (lvalue);
- assert (type == NUMERIC || type == ALPHA);
-
- compute->rvalue = expr_parse (default_dict,
- type == ALPHA ? EXPR_STRING : EXPR_NUMBER);
- if (compute->rvalue == NULL)
- return 0;
+ return (is_numeric
+ ? (is_vector ? compute_num_vec : compute_num)
+ : (is_vector ? compute_str_vec : compute_str));
+}
- if (type == NUMERIC)
- compute->h.proc = vector ? compute_num_vec : compute_num;
- else
- compute->h.proc = vector ? compute_str_vec : compute_str;
+/* Parses and returns an rvalue expression of the same type as
+ LVALUE, or a null pointer on failure. */
+static struct expression *
+parse_rvalue (const struct lvalue *lvalue)
+{
+ bool is_numeric = lvalue_get_type (lvalue) == NUMERIC;
- if (token != '.')
- {
- lex_error (_("expecting end of command"));
- return 0;
- }
-
- return 1;
+ return expr_parse (default_dict, is_numeric ? EXPR_NUMBER : EXPR_STRING);
}
/* Returns a new struct compute_trns after initializing its fields. */
compute_trns_create (void)
{
struct compute_trns *compute = xmalloc (sizeof *compute);
- compute->h.proc = NULL;
- compute->h.free = compute_trns_free;
compute->test = NULL;
compute->variable = NULL;
compute->vector = NULL;
/* Deletes all the fields in COMPUTE. */
static void
-compute_trns_free (struct trns_header *compute_)
+compute_trns_free (void *compute_)
{
- struct compute_trns *compute = (struct compute_trns *) compute_;
+ struct compute_trns *compute = compute_;
- expr_free (compute->test);
- expr_free (compute->element);
- expr_free (compute->rvalue);
+ if (compute != NULL)
+ {
+ expr_free (compute->test);
+ expr_free (compute->element);
+ expr_free (compute->rvalue);
+ free (compute);
+ }
}
\f
/* COMPUTE or IF target variable or vector element. */
struct expression *element; /* Destination vector element, or NULL. */
};
-/* Parses the target variable or vector elector into a new
+/* Parses the target variable or vector element into a new
`struct lvalue', which is returned. */
static struct lvalue *
lvalue_parse (void)
else
{
/* Variable name. */
- strncpy (lvalue->var_name, tokid, LONG_NAME_LEN);
- lvalue->var_name[LONG_NAME_LEN] = '\0';
+ str_copy_trunc (lvalue->var_name, sizeof lvalue->var_name, tokid);
lex_get ();
}
return lvalue;
{
if (lvalue->vector == NULL)
{
- struct variable *var
- = dict_lookup_var (default_dict, lvalue->var_name);
+ struct variable *var = dict_lookup_var (default_dict, lvalue->var_name);
if (var == NULL)
return NUMERIC;
else
}
/* Returns nonzero if LVALUE has a vector as its target. */
-static int
+static bool
lvalue_is_vector (const struct lvalue *lvalue)
{
return lvalue->vector != NULL;
/* Finalizes making LVALUE the target of COMPUTE, by creating the
target variable if necessary and setting fields in COMPUTE. */
static void
-lvalue_finalize (struct lvalue *lvalue,
- struct compute_trns *compute)
+lvalue_finalize (struct lvalue *lvalue, struct compute_trns *compute)
{
if (lvalue->vector == NULL)
{
static void
lvalue_destroy (struct lvalue *lvalue)
{
- if ( ! lvalue )
- return ;
+ if (lvalue == NULL)
+ return;
expr_free (lvalue->element);
free (lvalue);