--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include "data/casereader.h"
+#include "data/dataset.h"
+#include "data/subcase.h"
+#include "language/command.h"
+#include "language/lexer/lexer.h"
+#include "language/lexer/variable-parser.h"
+#include "math/sort.h"
+#include "output/tab.h"
+#include "output/table-item.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+enum
+ {
+ ROW_VAR,
+ COL_VAR,
+ DATA_VAR
+ };
+
+struct cmd_pivot
+ {
+ const struct variable **vars[3];
+ size_t n_vars[3];
+ };
+
+struct ccase *
+take_first_case (struct ccase *first, struct ccase *second, void *aux UNUSED)
+{
+ case_unref (second);
+ return first;
+}
+
+int
+cmd_debug_pivot (struct lexer *lexer, struct dataset *ds)
+{
+ const struct dictionary *dict = dataset_dict (ds);
+ struct cmd_pivot p;
+ struct casereader *reader;
+ struct subcase col_ordering, total_ordering, row_ordering;
+ struct casereader *columns, *cells, *columns_reader;
+ struct ccase *row, *prev, *column;
+ int col_idx;
+
+ memset (&p, 0, sizeof p);
+ while (lex_token (lexer) != T_ENDCMD)
+ {
+ lex_match (lexer, T_SLASH);
+ if (lex_match_id (lexer, "ROWS") )
+ {
+ lex_match (lexer, T_EQUALS);
+ if (!parse_variables_const (lexer, dict,
+ &p.vars[ROW_VAR], &p.n_vars[ROW_VAR],
+ PV_NO_DUPLICATE | PV_NO_SCRATCH))
+ return CMD_FAILURE;
+ }
+ else if (lex_match_id (lexer, "COLUMNS") )
+ {
+ lex_match (lexer, T_EQUALS);
+ if (!parse_variables_const (lexer, dict,
+ &p.vars[COL_VAR], &p.n_vars[COL_VAR],
+ PV_NO_DUPLICATE | PV_NO_SCRATCH))
+ return CMD_FAILURE;
+ }
+ else if (lex_match_id (lexer, "DATA") )
+ {
+ lex_match (lexer, T_EQUALS);
+ if (!parse_variables_const (lexer, dict,
+ &p.vars[DATA_VAR], &p.n_vars[DATA_VAR],
+ PV_NO_DUPLICATE | PV_NO_SCRATCH))
+ return CMD_FAILURE;
+ }
+ }
+
+
+ reader = proc_open (ds);
+
+ subcase_init_vars (&col_ordering, p.vars[COL_VAR], p.n_vars[COL_VAR]);
+ columns = sort_distinct_execute (casereader_clone (reader), &col_ordering,
+ take_first_case, NULL, NULL);
+ printf ("%lld column combinations\n",
+ (long long int) casereader_count_cases (columns));
+
+ subcase_init_vars (&total_ordering, p.vars[ROW_VAR], p.n_vars[ROW_VAR]);
+ subcase_add_vars_always (&total_ordering,
+ p.vars[COL_VAR], p.n_vars[COL_VAR]);
+ cells = sort_distinct_execute (reader, &total_ordering,
+ take_first_case, NULL, NULL);
+ printf ("%lld cells\n",
+ (long long int) casereader_count_cases (cells));
+
+ row = prev = column = NULL;
+ columns_reader = NULL;
+ subcase_init_vars (&row_ordering, p.vars[ROW_VAR], p.n_vars[ROW_VAR]);
+ for (;;)
+ {
+ struct ccase *c;
+
+ c = casereader_read (cells);
+ if (!c)
+ break;
+
+ if (!row || !subcase_equal (&row_ordering, row, &row_ordering, c))
+ {
+ int i;
+
+ if (row)
+ putchar ('\n');
+ case_unref (prev);
+ prev = row;
+ row = case_ref (c);
+
+ i = 0;
+ if (prev)
+ for (; i < p.n_vars[ROW_VAR]; i++)
+ {
+ if (!value_equal (case_data (row, p.vars[ROW_VAR][i]),
+ case_data (prev, p.vars[ROW_VAR][i]),
+ var_get_width (p.vars[ROW_VAR][i])))
+ break;
+ printf (" ");
+ }
+ for (; i < p.n_vars[ROW_VAR]; i++)
+ {
+ union value value;
+ const char *label;
+
+ value.f = case_num (row, p.vars[ROW_VAR][i]);
+ label = var_lookup_value_label (p.vars[ROW_VAR][i], &value);
+ if (label)
+ printf ("%7s ", label);
+ else
+ printf ("%7.0f ", value.f);
+ }
+ printf ("| ");
+
+ case_unref (column);
+ casereader_destroy (columns_reader);
+ columns_reader = casereader_clone (columns);
+ column = casereader_read (columns_reader);
+ col_idx = 0;
+ }
+
+ while (!subcase_equal (&col_ordering, column, &col_ordering, c))
+ {
+ case_unref (column);
+ column = casereader_read (columns_reader);
+ printf (" ");
+ col_idx++;
+ }
+
+ printf ("%7.0f ", case_num (c, p.vars[DATA_VAR][0]));
+ col_idx++;
+ column = casereader_read (columns_reader);
+ }
+ if (row)
+ putchar ('\n');
+ case_unref (row);
+ case_unref (prev);
+ case_unref (column);
+ casereader_destroy (columns_reader);
+
+ casereader_destroy (columns);
+ casereader_destroy (cells);
+ subcase_destroy (&col_ordering);
+ subcase_destroy (&row_ordering);
+
+ proc_commit (ds);
+
+ return CMD_SUCCESS;
+}