Fixed a bug causing pspp to crash when computed variables had no format
[pspp-builds.git] / src / sort.c
index de3ff977aa86af822e78cee258e69ea8d7dbabe2..7949ea5e24c303562ab1397d7bb2920c8dd2b33f 100644 (file)
@@ -24,7 +24,6 @@
 #include <stdlib.h>
 #include <errno.h>
 #include "alloc.h"
-#include "approx.h"
 #include "command.h"
 #include "error.h"
 #include "expr.h"
@@ -62,7 +61,7 @@ static int compare_case_lists (const void *, const void *);
 static int do_internal_sort (int separate);
 static int do_external_sort (int separate);
 int parse_sort_variables (void);
-void read_sort_output (int (*write_case) (void));
+void read_sort_output (write_case_func *write_case, write_case_data wc_data);
 
 /* Performs the SORT CASES procedures. */
 int
@@ -154,7 +153,7 @@ sort_cases (int separate)
 
   /* Not sure this is necessary but it's good to be safe. */
   if (separate && vfm_source == &sort_stream)
-    procedure (NULL, NULL, NULL);
+    procedure (NULL, NULL, NULL, NULL);
   
   /* SORT CASES cancels PROCESS IF. */
   expr_free (process_if_expr);
@@ -175,7 +174,7 @@ do_internal_sort (int separate)
   if (vfm_source != &vfm_disk_stream)
     {
       if (vfm_source != &vfm_memory_stream)
-       procedure (NULL, NULL, NULL);
+       procedure (NULL, NULL, NULL, NULL);
       if (vfm_source == &vfm_memory_stream)
        {
          struct case_list **case_tab = malloc (sizeof *case_tab
@@ -489,8 +488,8 @@ allocate_cases (void)
 {
   /* This is the size of one case. */
   const int case_size = (sizeof (struct repl_sel_tree)
-                        + (sizeof (union value)
-                            * (dict_get_value_cnt (default_dict) - 1))
+                        + dict_get_case_size (default_dict)
+                         - sizeof (union value)
                         + sizeof (struct repl_sel_tree *));
 
   x = NULL;
@@ -506,8 +505,8 @@ allocate_cases (void)
       for (i = 0; i < x_max; i++)
        {
          x[i] = malloc (sizeof (struct repl_sel_tree)
-                        + (sizeof (union value)
-                            * (dict_get_value_cnt (default_dict) - 1)));
+                         + dict_get_case_size (default_dict)
+                        - sizeof (union value));
          if (x[i] == NULL)
            break;
        }
@@ -733,8 +732,7 @@ write_initial_runs (int separate)
        J->rn = 0;
        J->fe = x[(x_max + j) / 2];
        J->fi = x[j / 2];
-       memset (J->record, 0,
-                dict_get_value_cnt (default_dict) * sizeof (union value));
+       memset (J->record, 0, dict_get_case_size (default_dict));
       }
   }
 
@@ -745,7 +743,7 @@ write_initial_runs (int separate)
        vfm_sink->destroy_sink ();
       vfm_sink = &sort_stream;
     }
-  procedure (NULL, NULL, NULL);
+  procedure (NULL, NULL, NULL, NULL);
 
   /* Final iterations of steps R4, R5, R6, R7, R2, R3, ... */
   for (;;)
@@ -850,7 +848,7 @@ compare_record (union value * a, union value * b)
 
       if (v->type == NUMERIC)
        {
-         if (approx_ne (a[v->fv].f, b[v->fv].f))
+         if (a[v->fv].f != b[v->fv].f)
            {
              result = (a[v->fv].f > b[v->fv].f) ? 1 : -1;
              break;
@@ -921,11 +919,10 @@ merge (void)
   order = MAX_MERGE_ORDER;
   if (x_max / order < MIN_BUFFER_SIZE_RECS)
     order = x_max / MIN_BUFFER_SIZE_RECS;
-  else if (x_max / order * sizeof (union value) * dict_get_value_cnt (default_dict)
+  else if (x_max / order * dict_get_case_size (default_dict)
           < MIN_BUFFER_SIZE_BYTES)
     order = x_max / (MIN_BUFFER_SIZE_BYTES
-                    / (sizeof (union value)
-                        * (dict_get_value_cnt (default_dict) - 1)));
+                     / dict_get_case_size (default_dict));
 
   /* Make sure the order of merge is bounded. */
   if (order < 2)
@@ -1065,9 +1062,8 @@ merge_once (int run_index[], int run_length[], int n_runs)
 
          buffered[i] = min (records_per_buffer, run_length[i]);
          for (j = 0; j < buffered[i]; j++)
-           if ((int) fread (x[j + ofs]->record, sizeof (union value),
-                            dict_get_value_cnt (default_dict), handle[i])
-               != dict_get_value_cnt (default_dict))
+           if (fread (x[j + ofs]->record,
+                       dict_get_case_size (default_dict), 1, handle[i]) != 1)
              {
                sprintf (tmp_extname, "%08x", run_index[i]);
                if (ferror (handle[i]))
@@ -1094,10 +1090,9 @@ merge_once (int run_index[], int run_length[], int n_runs)
                            x[buffer_ptr[i]]->record) > 0)
          min = i;
 
-      if ((int) fwrite (x[buffer_ptr[min]]->record, sizeof (union value),
-                       dict_get_value_cnt (default_dict),
-                        handle[N_INPUT_BUFFERS])
-         != dict_get_value_cnt (default_dict))
+      if (fwrite (x[buffer_ptr[min]]->record,
+                  dict_get_case_size (default_dict), 1,
+                  handle[N_INPUT_BUFFERS]) != 1)
        {
          sprintf (tmp_extname, "%08x", run_index[i]);
          msg (SE, _("%s: Error writing temporary file in "
@@ -1124,10 +1119,9 @@ merge_once (int run_index[], int run_length[], int n_runs)
 
              buffered[min] = min (records_per_buffer, run_length[min]);
              for (j = 0; j < buffered[min]; j++)
-               if ((int) fread (x[j + ofs]->record, sizeof (union value),
-                                dict_get_value_cnt (default_dict),
-                                 handle[min])
-                   != dict_get_value_cnt (default_dict))
+               if (fread (x[j + ofs]->record,
+                           dict_get_case_size (default_dict), 1, handle[min])
+                    != 1)
                  {
                    sprintf (tmp_extname, "%08x", run_index[min]);
                    if (ferror (handle[min]))
@@ -1221,16 +1215,16 @@ lossage:
 /* Reads all the records from the source stream and passes them
    to write_case(). */
 static void
-sort_stream_read (void)
+sort_stream_read (write_case_func *write_case, write_case_data wc_data)
 {
-  read_sort_output (write_case);
+  read_sort_output (write_case, wc_data);
 }
 
 /* Reads all the records from the output stream and passes them to the
    function provided, which must have an interface identical to
    write_case(). */
 void
-read_sort_output (int (*write_case) (void))
+read_sort_output (write_case_func *write_case, write_case_data wc_data)
 {
   int i;
   FILE *f;
@@ -1243,7 +1237,7 @@ read_sort_output (int (*write_case) (void))
       for (p = separate_case_tab; *p; p++)
        {
          temp_case = &(*p)->c;
-         write_case ();
+         write_case (wc_data);
        }
       
       free (separate_case_tab);
@@ -1275,7 +1269,7 @@ read_sort_output (int (*write_case) (void))
              break;
            }
 
-         if (!write_case ())
+         if (!write_case (wc_data))
            break;
        }