Implemented long variable names a la spss V12.
[pspp-builds.git] / src / count.c
index bbb41e55709828686c15f318331c8002086a653a..665248de6ca591ecb2de02406c00b8b12cd99ab5 100644 (file)
    02111-1307, USA. */
 
 #include <config.h>
-#include <assert.h>
+#include "error.h"
 #include <stdlib.h>
 #include "alloc.h"
-#include "approx.h"
+#include "case.h"
 #include "command.h"
+#include "dictionary.h"
 #include "error.h"
 #include "lexer.h"
 #include "str.h"
 
    Perhaps simultaneity could be implemented as an option.  On the
    other hand, what good are the above commands?  */
-
-#undef DEBUGGING
-/*#define DEBUGGING 1*/
-#include "debug-print.h"
 \f
 /* Definitions. */
 
@@ -111,7 +108,7 @@ struct cnt_var_info
     struct cnt_var_info *next;
 
     struct variable *d;                /* Destination variable. */
-    char n[9];                 /* Name of dest var. */
+    char n[SHORT_NAME_LEN + 1];        /* Name of dest var. */
 
     struct counting *c;                /* The counting specifications. */
   };
@@ -121,53 +118,23 @@ struct count_trns
     struct trns_header h;
     struct cnt_var_info *specs;
   };
-
-#if DEBUGGING
-static void debug_print (void);
-#endif
-
-/* First counting in chain. */
-static struct cnt_var_info *head;
 \f
 /* Parser. */
 
-static int count_trns_proc (struct trns_header *, struct ccase *);
-static void count_trns_free (struct trns_header *);
+static trns_proc_func count_trns_proc;
+static trns_free_func count_trns_free;
 
 static int parse_numeric_criteria (struct counting *);
 static int parse_string_criteria (struct counting *);
 
-int cmd_count (void);
-
-int
-internal_cmd_count (void)
-{
-  int code = cmd_count ();
-  if (!code)
-    {
-      struct count_trns c;
-      c.specs = head;
-      count_trns_free ((struct trns_header *) & c);
-    }
-  return code;
-}
-
 int
 cmd_count (void)
 {
-  /* Specification currently being parsed. */
-  struct cnt_var_info *cnt;
-
-  /* Counting currently being parsed. */
-  struct counting *c;
-
-  /* Return value from parsing function. */
-  int ret;
-
-  /* Transformation. */
-  struct count_trns *trns;
-
-  lex_match_id ("COUNT");
+  struct cnt_var_info *cnt;     /* Specification currently being parsed. */
+  struct counting *c;           /* Counting currently being parsed. */
+  int ret;                      /* Return value from parsing function. */
+  struct count_trns *trns;      /* Transformation. */
+  struct cnt_var_info *head;    /* First counting in chain. */
 
   /* Parses each slash-delimited specification. */
   head = cnt = xmalloc (sizeof *cnt);
@@ -181,7 +148,7 @@ cmd_count (void)
       /* Get destination struct variable, or at least its name. */
       if (!lex_force_id ())
        goto fail;
-      cnt->d = find_variable (tokid);
+      cnt->d = dict_lookup_var (default_dict, tokid);
       if (cnt->d)
        {
          if (cnt->d->type == ALPHA)
@@ -202,7 +169,8 @@ cmd_count (void)
        {
          c->next = NULL;
          c->v = NULL;
-         if (!parse_variables (NULL, &c->v, &c->n, PV_DUPLICATE | PV_SAME_TYPE))
+         if (!parse_variables (default_dict, &c->v, &c->n,
+                                PV_DUPLICATE | PV_SAME_TYPE))
            goto fail;
 
          if (!lex_force_match ('('))
@@ -232,18 +200,14 @@ cmd_count (void)
   for (cnt = head; cnt; cnt = cnt->next)
     if (!cnt->d)
       {
-       /* It's legal, though motivationally questionable, to count to
+       /* It's valid, though motivationally questionable, to count to
           the same dest var more than once. */
-       cnt->d = find_variable (cnt->n);
+       cnt->d = dict_lookup_var (default_dict, cnt->n);
 
-       if (!cnt->d)
-         cnt->d = force_create_variable (&default_dict, cnt->n, NUMERIC, 0);
+       if (cnt->d == NULL) 
+          cnt->d = dict_create_var_assert (default_dict, cnt->n, 0);
       }
 
-#if DEBUGGING
-  debug_print ();
-#endif
-
   trns = xmalloc (sizeof *trns);
   trns->h.proc = count_trns_proc;
   trns->h.free = count_trns_free;
@@ -280,13 +244,13 @@ parse_numeric_criteria (struct counting * c)
        }
 
       cur = &c->crit.n[n++];
-      if (token == T_NUM)
+      if (lex_is_number ())
        {
          cur->a = tokval;
          lex_get ();
          if (lex_match_id ("THRU"))
            {
-             if (token == T_NUM)
+             if (lex_is_number ())
                {
                  if (!lex_force_num ())
                    return 0;
@@ -318,7 +282,7 @@ parse_numeric_criteria (struct counting * c)
        {
          if (!lex_force_match_id ("THRU"))
            return 0;
-         if (token == T_NUM)
+         if (lex_is_number ())
            {
              cur->type = CNT_LOW;
              cur->a = tokval;
@@ -385,7 +349,7 @@ parse_string_criteria (struct counting * c)
       cur = &c->crit.s[n++];
       cur->type = CNT_SINGLE;
       cur->s = malloc (len + 1);
-      st_pad_copy (cur->s, ds_value (&tokstr), len + 1);
+      st_pad_copy (cur->s, ds_c_str (&tokstr), len + 1);
       lex_get ();
 
       lex_match (',');
@@ -404,16 +368,14 @@ static inline int
 count_numeric (struct counting * cnt, struct ccase * c)
 {
   int counter = 0;
-
-  struct cnt_num *num;
-
-  double cmp;
   int i;
 
   for (i = 0; i < cnt->n; i++)
     {
+      struct cnt_num *num;
+
       /* Extract the variable value and eliminate missing values. */
-      cmp = c->data[cnt->v[i]->fv].f;
+      double cmp = case_num (c, cnt->v[i]->fv);
       if (cmp == SYSMIS)
        {
          if (cnt->missing >= 1)
@@ -434,22 +396,22 @@ count_numeric (struct counting * cnt, struct ccase * c)
            assert (0);
            break;
          case CNT_SINGLE:
-           if (approx_ne (cmp, num->a))
+           if (cmp != num->a)
              break;
            counter++;
            goto done;
          case CNT_HIGH:
-           if (approx_lt (cmp, num->a))
+           if (cmp < num->a)
              break;
            counter++;
            goto done;
          case CNT_LOW:
-           if (approx_gt (cmp, num->a))
+           if (cmp > num->a)
              break;
            counter++;
            goto done;
          case CNT_RANGE:
-           if (approx_lt (cmp, num->a) || approx_gt (cmp, num->b))
+           if (cmp < num->a || cmp > num->b)
              break;
            counter++;
            goto done;
@@ -471,27 +433,21 @@ static inline int
 count_string (struct counting * cnt, struct ccase * c)
 {
   int counter = 0;
-
-  struct cnt_str *str;
-
-  char *cmp;
-  int len;
-
   int i;
 
   for (i = 0; i < cnt->n; i++)
     {
-      /* Extract the variable value, variable width. */
-      cmp = c->data[cnt->v[i]->fv].s;
-      len = cnt->v[i]->width;
+      struct cnt_str *str;
 
+      /* Extract the variable value, variable width. */
       for (str = cnt->crit.s;; str++)
        switch (str->type)
          {
          case CNT_ERROR:
            assert (0);
          case CNT_SINGLE:
-           if (memcmp (cmp, str->s, len))
+           if (memcmp (case_str (c, cnt->v[i]->fv), str->s,
+                        cnt->v[i]->width))
              break;
            counter++;
            goto done;
@@ -507,7 +463,8 @@ count_string (struct counting * cnt, struct ccase * c)
 
 /* Performs the COUNT transformation T on case C. */
 static int
-count_trns_proc (struct trns_header * trns, struct ccase * c)
+count_trns_proc (struct trns_header * trns, struct ccase * c,
+                 int case_num UNUSED)
 {
   struct cnt_var_info *info;
   struct counting *cnt;
@@ -521,7 +478,7 @@ count_trns_proc (struct trns_header * trns, struct ccase * c)
          counter += count_numeric (cnt, c);
        else
          counter += count_string (cnt, c);
-      c->data[info->d->fv].f = counter;
+      case_data_rw (c, info->d->fv)->f = counter;
     }
   return -1;
 }
@@ -561,81 +518,3 @@ count_trns_free (struct trns_header * t)
       free (iter);
     }
 }
-\f
-/* Debugging. */
-
-#if DEBUGGING
-static void
-debug_print (void)
-{
-  struct cnt_var_info *iter;
-  struct counting *i;
-  int j;
-
-  printf ("COUNT\n");
-  for (iter = head; iter; iter = iter->next)
-    {
-      printf ("  %s=", iter->d->name);
-      for (i = iter->c; i; i = i->next)
-       {
-         for (j = 0; j < i->n; j++)
-           printf ("%s%s", j ? " " : "", i->v[j]->name);
-         printf (" (");
-         if (i->v[0]->type == NUMERIC)
-           {
-             struct cnt_num *n;
-
-             if (i->missing == 2)
-               printf ("MISSING");
-             else if (i->missing == 1)
-               printf ("SYSMIS");
-             else
-               assert (i->missing == 0);
-
-             for (n = i->crit.n; n->type != CNT_SENTINEL; n++)
-               {
-                 if (i->missing && n != i->crit.n)
-                   printf (",");
-                 switch (n->type)
-                   {
-                   case CNT_SINGLE:
-                     printf ("%g", n->a);
-                     break;
-                   case CNT_HIGH:
-                     printf ("%g THRU HIGH", n->a);
-                     break;
-                   case CNT_LOW:
-                     printf ("LOW THRU %g", n->a);
-                     break;
-                   case CNT_RANGE:
-                     printf ("%g THRU %g", n->a, n->b);
-                     break;
-                   case CNT_ANY:
-                     printf ("LOW THRU HIGH");
-                     break;
-                   default:
-                     printf ("<ERROR %d>", n->type);
-                     break;
-                   }
-               }
-           }
-         else
-           {
-             struct cnt_str *s;
-
-             for (s = i->crit.s; s->type != CNT_SENTINEL; s++)
-               {
-                 if (s != i->crit.s)
-                   printf (",");
-                 if (s->type == CNT_SINGLE)
-                   printf ("'%s'", s->s);
-                 else
-                   printf ("<ERROR %d>", s->type);
-               }
-           }
-         printf (")  ");
-       }
-      printf ("\n");
-    }
-}
-#endif /* DEBUGGING */