X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fsort.c;h=7949ea5e24c303562ab1397d7bb2920c8dd2b33f;hb=e22db86f67a3b77124af022bbd734922c62c424c;hp=9f13a701b9ee41a43ad7fa7a566afdebcf4480a1;hpb=fcb9e49b2a2d57af7c001ae5d2eda9ac443ba36b;p=pspp diff --git a/src/sort.c b/src/sort.c index 9f13a701b9..7949ea5e24 100644 --- a/src/sort.c +++ b/src/sort.c @@ -18,19 +18,18 @@ 02111-1307, USA. */ #include +#include "sort.h" #include #include #include #include #include "alloc.h" -#include "approx.h" #include "command.h" #include "error.h" #include "expr.h" #include "heap.h" #include "lexer.h" #include "misc.h" -#include "sort.h" #include "str.h" #include "var.h" #include "vfm.h" @@ -57,17 +56,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 @@ -116,7 +110,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 ('(')) @@ -159,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); @@ -180,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 @@ -220,13 +214,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; @@ -237,27 +234,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; } /* External sort. */ @@ -437,10 +428,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) @@ -454,7 +445,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."), @@ -493,7 +488,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) + + dict_get_case_size (default_dict) + - sizeof (union value) + sizeof (struct repl_sel_tree *)); x = NULL; @@ -509,7 +505,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)); + + dict_get_case_size (default_dict) + - sizeof (union value)); if (x[i] == NULL) break; } @@ -735,7 +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, default_dict.nval * sizeof (union value)); + memset (J->record, 0, dict_get_case_size (default_dict)); } } @@ -746,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 (;;) @@ -851,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; @@ -922,10 +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) * default_dict.nval + 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) * (default_dict.nval - 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), - default_dict.nval, handle[i]) - != default_dict.nval) + 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,9 +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), - default_dict.nval, handle[N_INPUT_BUFFERS]) - != default_dict.nval) + 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 " @@ -1123,9 +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), - default_dict.nval, handle[min]) - != default_dict.nval) + 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])) @@ -1218,17 +1214,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; @@ -1241,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); @@ -1273,7 +1269,7 @@ read_sort_output (int (*write_case) (void)) break; } - if (!write_case ()) + if (!write_case (wc_data)) break; } @@ -1362,7 +1358,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: