Got rid of "struct long_vec", envector(), devector(), etc.
[pspp-builds.git] / src / sort.c
index e5feef94c208d545a1679d664a63c372353a42f3..d17075ade2a132091a40d97ce64a0bfaf0aa03dd 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "sort.h"
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -30,7 +31,6 @@
 #include "heap.h"
 #include "lexer.h"
 #include "misc.h"
-#include "sort.h"
 #include "str.h"
 #include "var.h"
 #include "vfm.h"
@@ -48,8 +48,6 @@
 #include <sys/stat.h>
 #endif
 
-#undef DEBUGGING
-/*#define DEBUGGING 1*/
 #include "debug-print.h"
 
 /* Variables to sort. */
@@ -59,17 +57,12 @@ int nv_sort;
 /* Used when internal-sorting to a separate file. */
 static struct case_list **separate_case_tab;
 
-/* Exported by qsort.c. */
-void blp_quicksort (void *pbase, size_t total_elems, size_t size,
-                   int (*cmp) (const void *, const void *),
-                   void *temp_buf);
-
 /* Other prototypes. */
 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
@@ -118,7 +111,7 @@ parse_sort_variables (void)
       int prev_nv_sort = nv_sort;
       int order = SRT_ASCEND;
 
-      if (!parse_variables (&default_dict, &v_sort, &nv_sort,
+      if (!parse_variables (default_dict, &v_sort, &nv_sort,
                            PV_NO_DUPLICATE | PV_APPEND | PV_NO_SCRATCH))
        return 0;
       if (lex_match ('('))
@@ -161,7 +154,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);
@@ -182,7 +175,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
@@ -222,13 +215,16 @@ do_internal_sort (int separate)
   return 0;
 }
 
-/* Compares the NV_SORT variables in V_SORT[] between the `case_list's
-   at _A and _B, and returns a strcmp()-type result. */
+/* Compares the NV_SORT variables in V_SORT[] between the
+   `case_list's at A and B, and returns a strcmp()-type
+   result. */
 static int
-compare_case_lists (const void *pa, const void *pb)
+compare_case_lists (const void *a_, const void *b_)
 {
-  struct case_list *a = *(struct case_list **) pa;
-  struct case_list *b = *(struct case_list **) pb;
+  struct case_list *const *pa = a_;
+  struct case_list *const *pb = b_;
+  struct case_list *a = *pa;
+  struct case_list *b = *pb;
   struct variable *v;
   int result = 0;
   int i;
@@ -239,27 +235,21 @@ compare_case_lists (const void *pa, const void *pb)
       
       if (v->type == NUMERIC)
        {
-         if (approx_ne (a->c.data[v->fv].f, b->c.data[v->fv].f))
-           {
-             result = (a->c.data[v->fv].f > b->c.data[v->fv].f) ? 1 : -1;
-             break;
-           }
+          double af = a->c.data[v->fv].f;
+          double bf = b->c.data[v->fv].f;
+
+          result = af < bf ? -1 : af > bf;
        }
       else
-       {
-         result = memcmp (a->c.data[v->fv].s, b->c.data[v->fv].s, v->width);
-         if (result != 0)
-           break;
-       }
-    }
+        result = memcmp (a->c.data[v->fv].s, b->c.data[v->fv].s, v->width);
 
-  if (v->p.srt.order == SRT_ASCEND)
-    return result;
-  else
-    {
-      assert (v->p.srt.order == SRT_DESCEND);
-      return -result;
+      if (result != 0)
+        break;
     }
+
+  if (v->p.srt.order == SRT_DESCEND)
+    result = -result;
+  return result;
 }
 \f
 /* External sort. */
@@ -439,10 +429,10 @@ allocate_file_handles (void)
   if (dir == NULL)
     dir = P_tmpdir;
 #endif
-#if __unix__
+#ifdef unix
   if (dir == NULL)
     dir = "/tmp";
-#elif __MSDOS__
+#elif defined (__MSDOS__)
   if (dir == NULL)
     dir = getenv ("TEMP");
   if (dir == NULL)
@@ -456,7 +446,11 @@ allocate_file_handles (void)
   buf = xmalloc (strlen (dir) + 1 + 4 + 8 + 4 + 1 + INT_DIGITS + 1);
   cp = spprintf (buf, "%s%c%04lX%04lXpspp", dir, DIR_SEPARATOR,
                 ((long) time (0)) & 0xffff, ((long) getpid ()) & 0xffff);
+#ifndef __MSDOS__
   if (-1 == mkdir (buf, S_IRWXU))
+#else
+  if (-1 == mkdir (buf))
+#endif
     {
       free (buf);
       msg (SE, _("%s: Cannot create temporary directory: %s."),
@@ -495,7 +489,8 @@ allocate_cases (void)
 {
   /* This is the size of one case. */
   const int case_size = (sizeof (struct repl_sel_tree)
-                        + sizeof (union value) * (default_dict.nval - 1)
+                        + (sizeof (union value)
+                            * (dict_get_value_cnt (default_dict) - 1))
                         + sizeof (struct repl_sel_tree *));
 
   x = NULL;
@@ -511,7 +506,8 @@ allocate_cases (void)
       for (i = 0; i < x_max; i++)
        {
          x[i] = malloc (sizeof (struct repl_sel_tree)
-                        + sizeof (union value) * (default_dict.nval - 1));
+                        + (sizeof (union value)
+                            * (dict_get_value_cnt (default_dict) - 1)));
          if (x[i] == NULL)
            break;
        }
@@ -737,7 +733,8 @@ write_initial_runs (int separate)
        J->rn = 0;
        J->fe = x[(x_max + j) / 2];
        J->fi = x[j / 2];
-       memset (J->record, 0, default_dict.nval * sizeof (union value));
+       memset (J->record, 0,
+                dict_get_value_cnt (default_dict) * sizeof (union value));
       }
   }
 
@@ -748,7 +745,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 (;;)
@@ -924,10 +921,11 @@ 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) * default_dict.nval
+  else if (x_max / order * sizeof (union value) * dict_get_value_cnt (default_dict)
           < MIN_BUFFER_SIZE_BYTES)
     order = x_max / (MIN_BUFFER_SIZE_BYTES
-                    / (sizeof (union value) * (default_dict.nval - 1)));
+                    / (sizeof (union value)
+                        * (dict_get_value_cnt (default_dict) - 1)));
 
   /* Make sure the order of merge is bounded. */
   if (order < 2)
@@ -1068,8 +1066,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),
-                            default_dict.nval, handle[i])
-               != default_dict.nval)
+                            dict_get_value_cnt (default_dict), handle[i])
+               != dict_get_value_cnt (default_dict))
              {
                sprintf (tmp_extname, "%08x", run_index[i]);
                if (ferror (handle[i]))
@@ -1097,8 +1095,9 @@ merge_once (int run_index[], int run_length[], int n_runs)
          min = i;
 
       if ((int) fwrite (x[buffer_ptr[min]]->record, sizeof (union value),
-                       default_dict.nval, handle[N_INPUT_BUFFERS])
-         != default_dict.nval)
+                       dict_get_value_cnt (default_dict),
+                        handle[N_INPUT_BUFFERS])
+         != dict_get_value_cnt (default_dict))
        {
          sprintf (tmp_extname, "%08x", run_index[i]);
          msg (SE, _("%s: Error writing temporary file in "
@@ -1126,8 +1125,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),
-                                default_dict.nval, handle[min])
-                   != default_dict.nval)
+                                dict_get_value_cnt (default_dict),
+                                 handle[min])
+                   != dict_get_value_cnt (default_dict))
                  {
                    sprintf (tmp_extname, "%08x", run_index[min]);
                    if (ferror (handle[min]))
@@ -1220,17 +1220,17 @@ lossage:
 
 /* Reads all the records from the source stream and passes them
    to write_case(). */
-void
-sort_stream_read (void)
+static 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 +1243,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 +1275,7 @@ read_sort_output (int (*write_case) (void))
              break;
            }
 
-         if (!write_case ())
+         if (!write_case (wc_data))
            break;
        }
 
@@ -1364,7 +1364,7 @@ sort_stream_write (void)
 }
 
 /* Switches mode from sink to source. */
-void
+static void
 sort_stream_mode (void)
 {
   /* If this is not done, then we get the following source/sink pairs: