コード例 #1
0
ファイル: variable_test.c プロジェクト: gpichon/compilation
int main(){
  struct Variable var;
  
  var_init(&var, "lol", "lolllvm", V_INT);
  assert (strcmp("lol", var_get_name(&var)) == 0);
  assert (strcmp("lolllvm", var_get_llvm_name(&var)) == 0);
  assert (var_is_int(&var) != 0);
  assert (var_is_float(&var) == 0);
  assert (var_get_type(&var) == V_INT);
  assert (var_is_special(&var) == 0);


  var_init(&var, "lol", "lolllvm", V_FLOAT|V_SPECIAL);
  var_info(&var);
  assert (var_is_int(&var) == 0);
  assert (var_is_float(&var) != 0);
  assert (var_get_type(&var) == V_FLOAT);
  assert (var_is_special(&var) != 0);
  
  var_set_value(&var, -131);
  assert (var_get_value(&var) == -131);

  var_set_value(&var, 1.234);
  assert (((var_get_value(&var)) - 1.234) < 0.00001);
  assert (var_get_value(&var) != 1);
      
  var_set_modified(&var, V_MODIFIED);
  assert (var_is_modified(&var) != 0);
  var_set_modified(&var, V_NULL);
  assert (var_is_modified(&var) == 0);

  
  var_set_type(&var, V_FLOAT);
  assert (var_is_int(&var) == 0);
  assert (var_is_float(&var) != 0);
  assert (var_get_type(&var) == V_FLOAT);

  var_set_special(&var, V_SPECIAL);
  assert (var_is_special(&var) != 0);


  var_set_type(&var, V_INT);
  assert (var_is_int(&var) != 0);
  assert (var_is_float(&var) == 0);
  assert (var_get_type(&var) == V_INT);

  var_set_access(&var, V_NULL);
  assert (var_is_writable(&var) == 0);
  var_set_access(&var, V_WRITABLE);
  assert (var_is_writable(&var) != 0);

  var.flags |= 1;
  assert (var_is_declared(&var) != 0);

  /* var_set_nb_args(&var, 13); */
  /* assert (var_get_nb_args(&var) == 13); */

  printf("Tests OK (sauf get_nb_args)\n");
}  
コード例 #2
0
static int operate(struct _var *var_d, struct _var *var_s, struct _operator *operator)
{
#ifdef DEBUG
printf(">>> OPERATING ON %d/%f/%d (%d) %d/%f/%d\n",
  var_get_int32(var_d), var_get_float(var_d), var_get_type(var_d),
  operator->operation,
  var_get_int32(var_s), var_get_float(var_s), var_get_type(var_s));
#endif

  switch(operator->operation)
  {
    case OPER_NOT:
      return var_not(var_d);
    case OPER_MUL:
      return var_mul(var_d, var_s);
    case OPER_DIV:
      return var_div(var_d, var_s);
    case OPER_MOD:
      return var_mod(var_d, var_s);
    case OPER_PLUS:
      return var_add(var_d, var_s);
    case OPER_MINUS:
      return var_sub(var_d, var_s);
    case OPER_LEFT_SHIFT:
      return var_shift_left(var_d, var_s);
    case OPER_RIGHT_SHIFT:
      return var_shift_right(var_d, var_s);
    case OPER_AND:
      return var_and(var_d, var_s);
    case OPER_XOR:
      return var_xor(var_d, var_s);
    case OPER_OR:
      return var_or(var_d, var_s);
    default:
      printf("Internal Error: WTF, bad operator %d\n", operator->operation);
      return 0;
  }
}
コード例 #3
0
ファイル: missing-values.c プロジェクト: RobertDash/pspp
int
cmd_missing_values (struct lexer *lexer, struct dataset *ds)
{
  struct dictionary *dict = dataset_dict (ds);
  struct variable **v = NULL;
  size_t nv;

  bool ok = true;

  while (lex_token (lexer) != T_ENDCMD)
    {
      size_t i;

      if (!parse_variables (lexer, dict, &v, &nv, PV_NONE))
        goto error;

      if (!lex_force_match (lexer, T_LPAREN))
        goto error;

      for (i = 0; i < nv; i++)
        var_clear_missing_values (v[i]);

      if (!lex_match (lexer, T_RPAREN))
        {
          struct missing_values mv;

          for (i = 0; i < nv; i++)
            if (var_get_type (v[i]) != var_get_type (v[0]))
              {
                const struct variable *n = var_is_numeric (v[0]) ? v[0] : v[i];
                const struct variable *s = var_is_numeric (v[0]) ? v[i] : v[0];
                msg (SE, _("Cannot mix numeric variables (e.g. %s) and "
                           "string variables (e.g. %s) within a single list."),
                     var_get_name (n), var_get_name (s));
                goto error;
              }

          if (var_is_numeric (v[0]))
            {
              mv_init (&mv, 0);
              while (!lex_match (lexer, T_RPAREN))
                {
                  enum fmt_type type = var_get_print_format (v[0])->type;
                  double x, y;
                  bool ok;

                  if (!parse_num_range (lexer, &x, &y, &type))
                    goto error;

                  ok = (x == y
                        ? mv_add_num (&mv, x)
                        : mv_add_range (&mv, x, y));
                  if (!ok)
                    ok = false;

                  lex_match (lexer, T_COMMA);
                }
            }
          else
            {
              mv_init (&mv, MV_MAX_STRING);
              while (!lex_match (lexer, T_RPAREN))
                {
                  uint8_t value[MV_MAX_STRING];
                  char *dict_mv;
                  size_t length;

                  if (!lex_force_string (lexer))
                    {
                      ok = false;
                      break;
                    }

                  dict_mv = recode_string (dict_get_encoding (dict), "UTF-8",
                                           lex_tokcstr (lexer),
                                           ss_length (lex_tokss (lexer)));
                  length = strlen (dict_mv);
                  if (length > MV_MAX_STRING)
                    {
                      /* XXX truncate graphemes not bytes */
                      msg (SE, _("Truncating missing value to maximum "
                                 "acceptable length (%d bytes)."),
                           MV_MAX_STRING);
                      length = MV_MAX_STRING;
                    }
                  memset (value, ' ', MV_MAX_STRING);
                  memcpy (value, dict_mv, length);
                  free (dict_mv);

                  if (!mv_add_str (&mv, value))
                    ok = false;

                  lex_get (lexer);
                  lex_match (lexer, T_COMMA);
                }
            }

          for (i = 0; i < nv; i++)
            {
              if (mv_is_resizable (&mv, var_get_width (v[i])))
                var_set_missing_values (v[i], &mv);
              else
                {
                  msg (SE, _("Missing values provided are too long to assign "
                             "to variable of width %d."),
                       var_get_width (v[i]));
                  ok = false;
                }
            }

          mv_destroy (&mv);
        }

      lex_match (lexer, T_SLASH);
      free (v);
      v = NULL;
    }

  free (v);
  return ok ? CMD_SUCCESS : CMD_FAILURE;

error:
  free (v);
  return CMD_FAILURE;
}
コード例 #4
0
ファイル: dialog-common.c プロジェクト: student-t/PSPP
/* Returns FALSE if the variables represented by the union of the rows
   currently selected by SOURCE widget, and contents of the DEST
   widget, are of different types.

   In other words, this function when passed as the argument to
   psppire_selector_set_allow, ensures that the selector selects only
   string  variables, or only numeric variables, not a mixture.
*/
gboolean
homogeneous_types (GtkWidget *source, GtkWidget *dest)
{
  gboolean ok;
  GtkTreeIter iter;
  gboolean retval = TRUE;

  GtkTreeModel *top_model = gtk_tree_view_get_model (GTK_TREE_VIEW (source));
  GtkTreeModel *model;

  PsppireDict *dict;
  GtkTreeSelection *selection;
  enum val_type type;
  GList *list, *l;
  bool have_type;


  get_base_model (top_model, NULL, &model, NULL);

  dict = PSPPIRE_DICT (model);

  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (source));

  list = gtk_tree_selection_get_selected_rows (selection, &model);

  /* Iterate through the selection of the source treeview */
  have_type = false;
  for (l = list; l ; l = l->next)
    {
      GtkTreePath *p = get_base_tree_path (top_model, l->data);
      gint *idx = gtk_tree_path_get_indices (p);
      const struct variable *v = psppire_dict_get_variable (dict, idx[0]);

      gtk_tree_path_free (p);

      if (have_type && var_get_type (v) != type)
        {
          retval = FALSE;
          break;
        }

      type = var_get_type (v);
      have_type = true;
    }

  g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
  g_list_free (list);

  if ( retval == FALSE )
    return FALSE;

  /* now deal with the dest widget */
  model = gtk_tree_view_get_model (GTK_TREE_VIEW (dest));

  for (ok = gtk_tree_model_get_iter_first (model, &iter);
       ok;
       ok = gtk_tree_model_iter_next (model, &iter))
    {
      const struct variable *v;
      gtk_tree_model_get (model, &iter, 0, &v, -1);

      if ( have_type && var_get_type (v) != type )
        {
          retval = FALSE;
          break;
        }

      type = var_get_type (v);
      have_type = true;
    }

  return retval;
}
コード例 #5
0
static int eval_expression_go(struct _asm_context *asm_context, struct _var *var, struct _operator *last_operator)
{
  char token[TOKENLEN];
  int token_type;
  struct _var var_stack[3];
  int var_stack_ptr = 1;
  struct _operator operator;
  int last_token_was_op = -1;

#ifdef DEBUG
printf("Enter eval_expression_go,  var=%d/%f/%d\n", var_get_int32(var), var_get_float(var), var_get_type(var));
#endif

  memcpy(&operator, last_operator, sizeof(struct _operator));
  VAR_COPY(&var_stack[0], var);

  while(1)
  {
#ifdef DEBUG
printf("eval_expression> going to grab a token\n");
#endif
    token_type = tokens_get(asm_context, token, TOKENLEN);

#ifdef DEBUG
printf("eval_expression> token=%s   var_stack_ptr=%d\n", token, var_stack_ptr);
#endif

    // Issue 15: Return an error if a stack is full with noe operator.
    if (var_stack_ptr == 3 && operator.operation == OPER_UNSET)
    {
      return -1;
    }

    if (token_type == TOKEN_QUOTED)
    {
      if (token[0] == '\\')
      {
        int e = tokens_escape_char(asm_context, (unsigned char *)token);
        if (e == 0) return -1;
        if (token[e+1] != 0)
        {
          print_error("Quoted literal too long.", asm_context);
          return -1;
        }
        sprintf(token, "%d", token[e]);
      }
        else
      {
        if (token[1]!=0)
        {
          print_error("Quoted literal too long.", asm_context);
          return -1;
        }
        sprintf(token, "%d", token[0]);
      }

      token_type = TOKEN_NUMBER;
    }

    // Open and close parenthesis
    if (IS_TOKEN(token,'('))
    {
      if (last_token_was_op == 0 && operator.operation != OPER_UNSET)
      {
        operate(&var_stack[var_stack_ptr-2], &var_stack[var_stack_ptr-1], last_operator);
        var_stack_ptr--;
        operator.operation = OPER_UNSET;

        VAR_COPY(var, &var_stack[var_stack_ptr-1]);
        tokens_push(asm_context, token, token_type);
        return 0;
      }

      if (operator.operation == OPER_UNSET && var_stack_ptr == 2)
      {
        // This is probably the x(r12) case.. so this is actually okay
        VAR_COPY(var, &var_stack[var_stack_ptr-1]);
        tokens_push(asm_context, token, token_type);
        return 0;
      }

      struct _var paren_var;
      struct _operator paren_operator;

      paren_operator.precedence = PREC_UNSET;
      paren_operator.operation = OPER_UNSET;
      memset(&paren_var, 0, sizeof(struct _var));

      if (eval_expression_go(asm_context, &paren_var, &paren_operator) != 0)
      {
        return -1;
      }

      last_token_was_op = 0;

#ifdef DEBUG
printf("Paren got back %d/%f/%d\n", var_get_int32(&paren_var), var_get_float(&paren_var), var_get_type(&paren_var));
#endif

      VAR_COPY(&var_stack[var_stack_ptr++], &paren_var);

      token_type = tokens_get(asm_context, token, TOKENLEN);
      if (!(token[1] == 0 && token[0] == ')'))
      {
        print_error("No matching ')'", asm_context);
        return -1;
      }
      continue;
    }

    if (IS_TOKEN(token,')'))
    {
      tokens_push(asm_context, token, token_type);
      break;
    }

    // End of expression
    if (IS_TOKEN(token,',') || IS_TOKEN(token,']') || token_type == TOKEN_EOF ||
        IS_TOKEN(token,'.'))
    {
      tokens_push(asm_context, token, token_type);
      break;
    }

    if (token_type == TOKEN_EOL)
    {
      //asm_context->tokens.line++;
      tokens_push(asm_context, token, token_type);
      break;
    }

    // Read number
    if (token_type == TOKEN_NUMBER)
    {
      last_token_was_op = 0;

      if (var_stack_ptr == 3)
      {
        print_error_unexp(token, asm_context);
        return -1;
      }

      var_set_int(&var_stack[var_stack_ptr++], atoll(token));
    }
      else
    if (token_type == TOKEN_FLOAT)
    {
      if (var_stack_ptr == 3)
      {
        print_error_unexp(token, asm_context);
        return -1;
      }

      var_set_float(&var_stack[var_stack_ptr++], atof(token));
    }
      else
    if (token_type == TOKEN_SYMBOL)
    {
      last_token_was_op = 1;

      struct _operator operator_prev;
      memcpy(&operator_prev, &operator, sizeof(struct _operator));

      if (get_operator(token, &operator) == -1)
      {
        print_error_unexp(token, asm_context);
        return -1;
      }

      // Issue 15: 2015-July-21 mkohn - If operator is ~ then reverse
      // the next number.
      if (operator.operation == OPER_NOT)
      {
        int64_t num;

        if (parse_unary(asm_context, &num, OPER_NOT) != 0) { return -1; }

        if (var_stack_ptr == 3)
        {
          print_error_unexp(token, asm_context);
          return -1;
        }

        var_set_int(&var_stack[var_stack_ptr++], num);
        memcpy(&operator, &operator_prev, sizeof(struct _operator));

        last_token_was_op = 0;

        continue;
      }

      // Stack pointer probably shouldn't be less than 2
      if (var_stack_ptr == 0)
      {
        printf("Error: Unexpected operator '%s' at %s:%d\n", token, asm_context->tokens.filename, asm_context->tokens.line);
        return -1;
      }

#ifdef DEBUG
printf("TOKEN %s: precedence %d %d\n", token, last_operator->precedence, operator.precedence);
#endif

      if (last_operator->precedence == PREC_UNSET)
      {
        memcpy(last_operator, &operator, sizeof(struct _operator));
      }
        else
      if (last_operator->precedence > operator.precedence)
      {
        if (eval_expression_go(asm_context, &var_stack[var_stack_ptr-1], &operator) == -1)
        {
          return -1;
        }
      }
        else
      {
        operate(&var_stack[var_stack_ptr-2], &var_stack[var_stack_ptr-1], last_operator);
        var_stack_ptr--;
        memcpy(last_operator, &operator, sizeof(struct _operator));
      }
    }
      else
    {
      if (asm_context->pass != 1)
      {
        print_error_unexp(token, asm_context);
      }
      return -1;
    }
  }

#ifdef DEBUG
printf("going to leave  operation=%d\n", last_operator->operation);
PRINT_STACK()
#endif

  if (last_operator->operation != OPER_UNSET)
  {
    operate(&var_stack[var_stack_ptr-2], &var_stack[var_stack_ptr-1], last_operator);
    var_stack_ptr--;
  }

  VAR_COPY(var, &var_stack[var_stack_ptr-1]);

  return 0;
}
コード例 #6
0
ファイル: dialog-common.c プロジェクト: RobertDash/pspp
/* Returns FALSE if the variables represented by the union of the rows
   currently selected by SOURCE widget, and contents of the DEST
   widget, are of different types.

   In other words, this function when passed as the argument to
   psppire_selector_set_allow, ensures that the selector selects only
   string  variables, or only numeric variables, not a mixture.
*/
gboolean
homogeneous_types (GtkWidget *source, GtkWidget *dest)
{
  gboolean ok;
  GtkTreeIter iter;
  gboolean retval = TRUE;

  GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (source));

  PsppireDict *dict;
  GtkTreeSelection *selection;
  enum val_type type = -1;
  GList *list, *l;

  while (GTK_IS_TREE_MODEL_FILTER (model))
    {
      model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
    }

  dict = PSPPIRE_DICT (model);

  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (source));

  list = gtk_tree_selection_get_selected_rows (selection, &model);

  /* Iterate through the selection of the source treeview */
  for (l = list; l ; l = l->next)
    {
      GtkTreePath *path = l->data;

      GtkTreePath *fpath =
	gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER (model), path);

      gint *idx = gtk_tree_path_get_indices (fpath);

      const struct variable *v = psppire_dict_get_variable (dict, idx[0]);

      gtk_tree_path_free (fpath);

      if ( type != -1 )
	{
	  if ( var_get_type (v) != type )
	    {
	      retval = FALSE;
	      break;
	    }
	}

      type = var_get_type (v);
    }

  g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
  g_list_free (list);

  if ( retval == FALSE )
    return FALSE;

  /* now deal with the dest widget */
  model = gtk_tree_view_get_model (GTK_TREE_VIEW (dest));

  for (ok = gtk_tree_model_get_iter_first (model, &iter);
       ok;
       ok = gtk_tree_model_iter_next (model, &iter))
    {
      const struct variable *v;
      gtk_tree_model_get (model, &iter, 0, &v, -1);

      if ( type != -1 )
	{
	  if ( var_get_type (v) != type )
	    {
	      retval = FALSE;
	      break;
	    }
	}

      type = var_get_type (v);
    }

  return retval;
}
コード例 #7
0
ファイル: aggregate.c プロジェクト: student-t/PSPP
/* Parse all the aggregate functions. */
static bool
parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict,
			   struct agr_proc *agr)
{
  struct agr_var *tail; /* Tail of linked list starting at agr->vars. */

  /* Parse everything. */
  tail = NULL;
  for (;;)
    {
      char **dest;
      char **dest_label;
      size_t n_dest;
      struct string function_name;

      enum mv_class exclude;
      const struct agr_func *function;
      int func_index;

      union agr_argument arg[2];

      const struct variable **src;
      size_t n_src;

      size_t i;

      dest = NULL;
      dest_label = NULL;
      n_dest = 0;
      src = NULL;
      function = NULL;
      n_src = 0;
      arg[0].c = NULL;
      arg[1].c = NULL;
      ds_init_empty (&function_name);

      /* Parse the list of target variables. */
      while (!lex_match (lexer, T_EQUALS))
	{
	  size_t n_dest_prev = n_dest;

	  if (!parse_DATA_LIST_vars (lexer, dict, &dest, &n_dest,
                                     (PV_APPEND | PV_SINGLE | PV_NO_SCRATCH
                                      | PV_NO_DUPLICATE)))
	    goto error;

	  /* Assign empty labels. */
	  {
	    int j;

	    dest_label = xnrealloc (dest_label, n_dest, sizeof *dest_label);
	    for (j = n_dest_prev; j < n_dest; j++)
	      dest_label[j] = NULL;
	  }



	  if (lex_is_string (lexer))
	    {
	      dest_label[n_dest - 1] = xstrdup (lex_tokcstr (lexer));
	      lex_get (lexer);
	    }
	}

      /* Get the name of the aggregation function. */
      if (lex_token (lexer) != T_ID)
	{
	  lex_error (lexer, _("expecting aggregation function"));
	  goto error;
	}

      ds_assign_substring (&function_name, lex_tokss (lexer));
      exclude = ds_chomp_byte (&function_name, '.') ? MV_SYSTEM : MV_ANY;

      for (function = agr_func_tab; function->name; function++)
	if (!c_strcasecmp (function->name, ds_cstr (&function_name)))
	  break;
      if (NULL == function->name)
	{
	  msg (SE, _("Unknown aggregation function %s."),
	       ds_cstr (&function_name));
	  goto error;
	}
      ds_destroy (&function_name);
      func_index = function - agr_func_tab;
      lex_get (lexer);

      /* Check for leading lparen. */
      if (!lex_match (lexer, T_LPAREN))
	{
	  if (function->src_vars == AGR_SV_YES)
	    {
              lex_force_match (lexer, T_LPAREN);
	      goto error;
	    }
	}
      else
        {
	  /* Parse list of source variables. */
	  {
	    int pv_opts = PV_NO_SCRATCH;

	    if (func_index == SUM || func_index == MEAN || func_index == SD)
	      pv_opts |= PV_NUMERIC;
	    else if (function->n_args)
	      pv_opts |= PV_SAME_TYPE;

	    if (!parse_variables_const (lexer, dict, &src, &n_src, pv_opts))
	      goto error;
	  }

	  /* Parse function arguments, for those functions that
	     require arguments. */
	  if (function->n_args != 0)
	    for (i = 0; i < function->n_args; i++)
	      {
		int type;

		lex_match (lexer, T_COMMA);
		if (lex_is_string (lexer))
		  {
		    arg[i].c = recode_string (dict_get_encoding (agr->dict),
                                              "UTF-8", lex_tokcstr (lexer),
                                              -1);
		    type = VAL_STRING;
		  }
		else if (lex_is_number (lexer))
		  {
		    arg[i].f = lex_tokval (lexer);
		    type = VAL_NUMERIC;
		  }
                else
                  {
		    msg (SE, _("Missing argument %zu to %s."),
                         i + 1, function->name);
		    goto error;
		  }

		lex_get (lexer);

		if (type != var_get_type (src[0]))
		  {
		    msg (SE, _("Arguments to %s must be of same type as "
			       "source variables."),
			 function->name);
		    goto error;
		  }
	      }

	  /* Trailing rparen. */
	  if (!lex_force_match (lexer, T_RPAREN))
            goto error;

	  /* Now check that the number of source variables match
	     the number of target variables.  If we check earlier
	     than this, the user can get very misleading error
	     message, i.e. `AGGREGATE x=SUM(y t).' will get this
	     error message when a proper message would be more
	     like `unknown variable t'. */
	  if (n_src != n_dest)
	    {
	      msg (SE, _("Number of source variables (%zu) does not match "
			 "number of target variables (%zu)."),
		    n_src, n_dest);
	      goto error;
	    }

          if ((func_index == PIN || func_index == POUT
              || func_index == FIN || func_index == FOUT)
              && (var_is_numeric (src[0])
                  ? arg[0].f > arg[1].f
                  : str_compare_rpad (arg[0].c, arg[1].c) > 0))
            {
              union agr_argument t = arg[0];
              arg[0] = arg[1];
              arg[1] = t;

              msg (SW, _("The value arguments passed to the %s function "
                         "are out-of-order.  They will be treated as if "
                         "they had been specified in the correct order."),
                   function->name);
            }
	}

      /* Finally add these to the linked list of aggregation
         variables. */
      for (i = 0; i < n_dest; i++)
	{
	  struct agr_var *v = xzalloc (sizeof *v);

	  /* Add variable to chain. */
	  if (agr->agr_vars != NULL)
	    tail->next = v;
	  else
	    agr->agr_vars = v;
          tail = v;
	  tail->next = NULL;
          v->moments = NULL;

	  /* Create the target variable in the aggregate
             dictionary. */
	  {
	    struct variable *destvar;

	    v->function = func_index;

	    if (src)
	      {
		v->src = src[i];

		if (var_is_alpha (src[i]))
		  {
		    v->function |= FSTRING;
		    v->string = xmalloc (var_get_width (src[i]));
		  }

		if (function->alpha_type == VAL_STRING)
		  destvar = dict_clone_var_as (agr->dict, v->src, dest[i]);
		else
                  {
                    assert (var_is_numeric (v->src)
                            || function->alpha_type == VAL_NUMERIC);
                    destvar = dict_create_var (agr->dict, dest[i], 0);
                    if (destvar != NULL)
                      {
                        struct fmt_spec f;
                        if ((func_index == N || func_index == NMISS)
                            && dict_get_weight (dict) != NULL)
                          f = fmt_for_output (FMT_F, 8, 2);
                        else
                          f = function->format;
                        var_set_both_formats (destvar, &f);
                      }
                  }
	      } else {
                struct fmt_spec f;
		v->src = NULL;
		destvar = dict_create_var (agr->dict, dest[i], 0);
		if (destvar != NULL)
		  {
		    if ((func_index == N || func_index == NMISS)
			&& dict_get_weight (dict) != NULL)
		      f = fmt_for_output (FMT_F, 8, 2);
		    else
		      f = function->format;
		    var_set_both_formats (destvar, &f);
		  }
	    }

	    if (!destvar)
	      {
		msg (SE, _("Variable name %s is not unique within the "
			   "aggregate file dictionary, which contains "
			   "the aggregate variables and the break "
			   "variables."),
		     dest[i]);
		goto error;
	      }

	    free (dest[i]);
	    if (dest_label[i])
              var_set_label (destvar, dest_label[i]);

	    v->dest = destvar;
	  }

	  v->exclude = exclude;

	  if (v->src != NULL)
	    {
	      int j;

	      if (var_is_numeric (v->src))
		for (j = 0; j < function->n_args; j++)
		  v->arg[j].f = arg[j].f;
	      else
		for (j = 0; j < function->n_args; j++)
		  v->arg[j].c = xstrdup (arg[j].c);
	    }
	}

      if (src != NULL && var_is_alpha (src[0]))
	for (i = 0; i < function->n_args; i++)
	  {
	    free (arg[i].c);
	    arg[i].c = NULL;
	  }

      free (src);
      free (dest);
      free (dest_label);

      if (!lex_match (lexer, T_SLASH))
	{
	  if (lex_token (lexer) == T_ENDCMD)
	    return true;

	  lex_error (lexer, "expecting end of command");
	  return false;
	}
      continue;

    error:
      ds_destroy (&function_name);
      for (i = 0; i < n_dest; i++)
	{
	  free (dest[i]);
	  free (dest_label[i]);
	}
      free (dest);
      free (dest_label);
      free (arg[0].c);
      free (arg[1].c);
      if (src && n_src && var_is_alpha (src[0]))
	for (i = 0; i < function->n_args; i++)
	  {
	    free (arg[i].c);
	    arg[i].c = NULL;
	  }
      free (src);

      return false;
    }
}