#include <errno.h>
#include "algorithm.h"
#include "alloc.h"
-#include "bool.h"
+#include <stdbool.h>
#include "case.h"
#include "casefile.h"
#include "command.h"
#include "lexer.h"
#include "misc.h"
#include "settings.h"
+#include "sort-prs.h"
#include "str.h"
#include "var.h"
#include "vfm.h"
#include "vfmP.h"
-#include "debug-print.h"
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
-/* Sort direction. */
-enum sort_direction
- {
- SRT_ASCEND, /* A, B, C, ..., X, Y, Z. */
- SRT_DESCEND /* Z, Y, X, ..., C, B, A. */
- };
-
-/* A sort criterion. */
-struct sort_criterion
- {
- int fv; /* Variable data index. */
- int width; /* 0=numeric, otherwise string widthe. */
- enum sort_direction dir; /* Sort direction. */
- };
-
-/* A set of sort criteria. */
-struct sort_criteria
- {
- struct sort_criterion *crits;
- size_t crit_cnt;
- };
+#include "debug-print.h"
/* These should only be changed for testing purposes. */
static int min_buffers = 64;
lex_match (T_BY);
- criteria = sort_parse_criteria (default_dict, NULL, NULL, NULL);
+ criteria = sort_parse_criteria (default_dict, NULL, NULL, NULL, NULL);
if (criteria == NULL)
return CMD_FAILURE;
- if (test_mode && lex_match ('/'))
+ if (get_testing_mode () && lex_match ('/'))
{
if (!lex_force_match_id ("BUFFERS") || !lex_match ('=')
|| !lex_force_int ())
return sort_execute (casefile_get_reader (src), criteria);
}
-/* Parses a list of sort keys and returns a struct sort_criteria
- based on it. Returns a null pointer on error.
- If SAW_DIRECTION is nonnull, sets *SAW_DIRECTION to true if at
- least one parenthesized sort direction was specified, false
- otherwise. */
-struct sort_criteria *
-sort_parse_criteria (const struct dictionary *dict,
- struct variable ***vars, int *var_cnt,
- bool *saw_direction)
-{
- struct sort_criteria *criteria;
- struct variable **local_vars = NULL;
- size_t local_var_cnt;
-
- assert ((vars == NULL) == (var_cnt == NULL));
- if (vars == NULL)
- {
- vars = &local_vars;
- var_cnt = &local_var_cnt;
- }
-
- criteria = xmalloc (sizeof *criteria);
- criteria->crits = NULL;
- criteria->crit_cnt = 0;
-
- *vars = NULL;
- *var_cnt = 0;
- if (saw_direction != NULL)
- *saw_direction = false;
-
- do
- {
- int prev_var_cnt = *var_cnt;
- enum sort_direction direction;
-
- /* Variables. */
- if (!parse_variables (dict, vars, var_cnt,
- PV_NO_DUPLICATE | PV_APPEND | PV_NO_SCRATCH))
- goto error;
-
- /* Sort direction. */
- if (lex_match ('('))
- {
- if (lex_match_id ("D") || lex_match_id ("DOWN"))
- direction = SRT_DESCEND;
- else if (lex_match_id ("A") || lex_match_id ("UP"))
- direction = SRT_ASCEND;
- else
- {
- msg (SE, _("`A' or `D' expected inside parentheses."));
- goto error;
- }
- if (!lex_match (')'))
- {
- msg (SE, _("`)' expected."));
- goto error;
- }
- *saw_direction = true;
- }
- else
- direction = SRT_ASCEND;
-
- criteria->crits = xrealloc (criteria->crits,
- sizeof *criteria->crits * *var_cnt);
- criteria->crit_cnt = *var_cnt;
- for (; prev_var_cnt < criteria->crit_cnt; prev_var_cnt++)
- {
- struct sort_criterion *c = &criteria->crits[prev_var_cnt];
- c->fv = (*vars)[prev_var_cnt]->fv;
- c->width = (*vars)[prev_var_cnt]->width;
- c->dir = direction;
- }
- }
- while (token != '.' && token != '/');
-
- free (local_vars);
- return criteria;
-
- error:
- free (local_vars);
- sort_destroy_criteria (criteria);
- return NULL;
-}
-
-/* Destroys a SORT CASES program. */
-void
-sort_destroy_criteria (struct sort_criteria *criteria)
-{
- if (criteria != NULL)
- {
- free (criteria->crits);
- free (criteria);
- }
-}
/* Reads all the cases from READER, which is destroyed. Sorts
the cases according to CRITERIA. Returns the sorted cases in
dst = casefile_create (casefile_get_value_cnt (src));
if (case_cnt != 0)
{
- struct indexed_case *cases = malloc (sizeof *cases * case_cnt);
+ struct indexed_case *cases = nmalloc (sizeof *cases, case_cnt);
if (cases != NULL)
{
unsigned long i;
xsrt->value_cnt = casefile_get_value_cnt (casereader_get_casefile (reader));
xsrt->run_cap = 512;
xsrt->run_cnt = 0;
- xsrt->runs = xmalloc (sizeof *xsrt->runs * xsrt->run_cap);
+ xsrt->runs = xnmalloc (xsrt->run_cap, sizeof *xsrt->runs);
if (write_runs (xsrt, reader))
{
struct casefile *output = merge (xsrt);
approx_case_cost = (sizeof *irs->records
+ irs->xsrt->value_cnt * sizeof (union value)
+ 4 * sizeof (void *));
- max_cases = get_max_workspace() / approx_case_cost;
+ max_cases = get_workspace() / approx_case_cost;
if (max_cases > max_buffers)
max_cases = max_buffers;
- irs->records = malloc (sizeof *irs->records * max_cases);
- for (i = 0; i < max_cases; i++)
- if (!case_try_create (&irs->records[i].record, irs->xsrt->value_cnt))
- {
- max_cases = i;
- break;
- }
+ irs->records = nmalloc (sizeof *irs->records, max_cases);
+ if (irs->records != NULL)
+ for (i = 0; i < max_cases; i++)
+ if (!case_try_create (&irs->records[i].record, irs->xsrt->value_cnt))
+ {
+ max_cases = i;
+ break;
+ }
irs->record_cap = max_cases;
/* Fail if we didn't allocate an acceptable number of cases. */
msg (SE, _("Out of memory. Could not allocate room for minimum of %d "
"cases of %d bytes each. (PSPP workspace is currently "
"restricted to a maximum of %d KB.)"),
- min_buffers, approx_case_cost, get_max_workspace() / 1024);
+ min_buffers, approx_case_cost, get_workspace() / 1024);
return 0;
}
return 1;
if (xsrt->run_cnt >= xsrt->run_cap)
{
xsrt->run_cap *= 2;
- xsrt->runs = xrealloc (xsrt->runs,
- sizeof *xsrt->runs * xsrt->run_cap);
+ xsrt->runs = xnrealloc (xsrt->runs,
+ xsrt->run_cap, sizeof *xsrt->runs);
}
xsrt->runs[xsrt->run_cnt++] = irs->casefile;
irs->casefile = NULL;
int i;
/* Open input files. */
- runs = xmalloc (sizeof *runs * run_cnt);
+ runs = xnmalloc (run_cnt, sizeof *runs);
for (i = 0; i < run_cnt; i++)
{
struct run *r = &runs[i];