Rename procedure.[ch] to dataset.[ch].
[pspp-builds.git] / src / language / data-io / list.q
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2009-2011 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include "data/casegrouper.h"
24 #include "data/casereader.h"
25 #include "data/dataset.h"
26 #include "data/dictionary.h"
27 #include "data/data-out.h"
28 #include "data/format.h"
29 #include "data/subcase.h"
30 #include "data/variable.h"
31 #include "language/command.h"
32 #include "language/dictionary/split-file.h"
33 #include "language/lexer/lexer.h"
34 #include "libpspp/compiler.h"
35 #include "libpspp/ll.h"
36 #include "libpspp/message.h"
37 #include "libpspp/misc.h"
38 #include "output/tab.h"
39 #include "output/table-item.h"
40
41 #include "gl/intprops.h"
42 #include "gl/minmax.h"
43 #include "gl/xalloc.h"
44 #include "gl/xmalloca.h"
45
46 #include "gettext.h"
47 #define _(msgid) gettext (msgid)
48
49 /* (headers) */
50
51 /* (specification)
52    list (lst_):
53      *variables=varlist("PV_NO_SCRATCH");
54      cases=:from n:first,"%s>0"/by n:step,"%s>0"/ *to n:last,"%s>0";
55      +format=numbering:numbered/!unnumbered,
56              wrap:!wrap/single.
57 */
58 /* (declarations) */
59 /* (functions) */
60
61 /* Parsed command. */
62 static struct cmd_list cmd;
63
64 /* Parses and executes the LIST procedure. */
65 int
66 cmd_list (struct lexer *lexer, struct dataset *ds)
67 {
68   struct dictionary *dict = dataset_dict (ds);
69   struct casegrouper *grouper;
70   struct casereader *group;
71   struct subcase sc;
72   size_t i;
73   bool ok;
74
75   if (!parse_list (lexer, ds, &cmd, NULL))
76     return CMD_FAILURE;
77
78   /* Fill in defaults. */
79   if (cmd.step == LONG_MIN)
80     cmd.step = 1;
81   if (cmd.first == LONG_MIN)
82     cmd.first = 1;
83   if (cmd.last == LONG_MIN)
84     cmd.last = LONG_MAX;
85   if (!cmd.sbc_variables)
86     dict_get_vars (dict, &cmd.v_variables, &cmd.n_variables,
87                    DC_SYSTEM | DC_SCRATCH);
88   if (cmd.n_variables == 0)
89     {
90       msg (SE, _("No variables specified."));
91       return CMD_FAILURE;
92     }
93
94   /* Verify arguments. */
95   if (cmd.first > cmd.last)
96     {
97       int t;
98       msg (SW, _("The first case (%ld) specified precedes the last case (%ld) "
99            "specified.  The values will be swapped."), cmd.first, cmd.last);
100       t = cmd.first;
101       cmd.first = cmd.last;
102       cmd.last = t;
103     }
104   if (cmd.first < 1)
105     {
106       msg (SW, _("The first case (%ld) to list is less than 1.  The value is "
107            "being reset to 1."), cmd.first);
108       cmd.first = 1;
109     }
110   if (cmd.last < 1)
111     {
112       msg (SW, _("The last case (%ld) to list is less than 1.  The value is "
113            "being reset to 1."), cmd.last);
114       cmd.last = 1;
115     }
116   if (cmd.step < 1)
117     {
118       msg (SW, _("The step value %ld is less than 1.  The value is being "
119            "reset to 1."), cmd.step);
120       cmd.step = 1;
121     }
122
123   subcase_init_empty (&sc);
124   for (i = 0; i < cmd.n_variables; i++)
125     subcase_add_var (&sc, cmd.v_variables[i], SC_ASCEND);
126
127   grouper = casegrouper_create_splits (proc_open (ds), dict);
128   while (casegrouper_get_next_group (grouper, &group))
129     {
130       struct ccase *ccase;
131       struct table *t;
132
133       group = casereader_project (group, &sc);
134       if (cmd.numbering == LST_NUMBERED)
135         group = casereader_create_arithmetic_sequence (group, 1, 1);
136       group = casereader_select (group, cmd.first - 1,
137                                  (cmd.last != LONG_MAX ? cmd.last
138                                   : CASENUMBER_MAX), cmd.step);
139
140       ccase = casereader_peek (group, 0);
141       if (ccase != NULL)
142         {
143           output_split_file_values (ds, ccase);
144           case_unref (ccase);
145         }
146
147       if (cmd.numbering == LST_NUMBERED)
148         {
149           struct fmt_spec fmt;
150           size_t col;
151           int width;
152
153           width = cmd.last == LONG_MAX ? 5 : intlog10 (cmd.last);
154           fmt = fmt_for_output (FMT_F, width, 0);
155           col = caseproto_get_n_widths (casereader_get_proto (group)) - 1;
156
157           t = table_from_casereader (group, col, _("Case Number"), &fmt);
158         }
159       else
160         t = NULL;
161
162       for (i = 0; i < cmd.n_variables; i++)
163         {
164           const struct variable *var = cmd.v_variables[i];
165           struct table *c;
166
167           c = table_from_casereader (group, i, var_get_name (var),
168                                      var_get_print_format (var));
169           t = table_hpaste (t, c);
170         }
171
172       casereader_destroy (group);
173
174       table_item_submit (table_item_create (t, "Data List"));
175     }
176   ok = casegrouper_destroy (grouper);
177   ok = proc_commit (ds) && ok;
178
179   subcase_destroy (&sc);
180   free (cmd.v_variables);
181
182   return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
183 }
184
185 /*
186    Local Variables:
187    mode: c
188    End:
189 */