738b667183523a210d6530b74ef4f15ea2b598e8
[pspp-builds.git] / src / language / data-io / list.q
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2009 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 "intprops.h"
24 #include "xmalloca.h"
25
26 #include <data/casegrouper.h>
27 #include <data/casereader.h>
28 #include <data/dictionary.h>
29 #include <data/data-out.h>
30 #include <data/format.h>
31 #include <data/procedure.h>
32 #include <data/subcase.h>
33 #include <data/variable.h>
34 #include <language/command.h>
35 #include <language/dictionary/split-file.h>
36 #include <language/lexer/lexer.h>
37 #include <libpspp/compiler.h>
38 #include <libpspp/ll.h>
39 #include <libpspp/message.h>
40 #include <libpspp/misc.h>
41 #include <output/tab.h>
42 #include <output/table-item.h>
43
44 #include "minmax.h"
45 #include "xalloc.h"
46
47 #include "gettext.h"
48 #define _(msgid) gettext (msgid)
49
50 /* (headers) */
51
52 /* (specification)
53    list (lst_):
54      *variables=varlist("PV_NO_SCRATCH");
55      cases=:from n:first,"%s>0"/by n:step,"%s>0"/ *to n:last,"%s>0";
56      +format=numbering:numbered/!unnumbered,
57              wrap:!wrap/single.
58 */
59 /* (declarations) */
60 /* (functions) */
61
62 /* Parsed command. */
63 static struct cmd_list cmd;
64
65 /* Parses and executes the LIST procedure. */
66 int
67 cmd_list (struct lexer *lexer, struct dataset *ds)
68 {
69   struct dictionary *dict = dataset_dict (ds);
70   struct casegrouper *grouper;
71   struct casereader *group;
72   struct subcase sc;
73   size_t i;
74   bool ok;
75
76   if (!parse_list (lexer, ds, &cmd, NULL))
77     return CMD_FAILURE;
78
79   /* Fill in defaults. */
80   if (cmd.step == LONG_MIN)
81     cmd.step = 1;
82   if (cmd.first == LONG_MIN)
83     cmd.first = 1;
84   if (cmd.last == LONG_MIN)
85     cmd.last = LONG_MAX;
86   if (!cmd.sbc_variables)
87     dict_get_vars (dict, &cmd.v_variables, &cmd.n_variables,
88                    DC_SYSTEM | DC_SCRATCH);
89   if (cmd.n_variables == 0)
90     {
91       msg (SE, _("No variables specified."));
92       return CMD_FAILURE;
93     }
94
95   /* Verify arguments. */
96   if (cmd.first > cmd.last)
97     {
98       int t;
99       msg (SW, _("The first case (%ld) specified precedes the last case (%ld) "
100            "specified.  The values will be swapped."), cmd.first, cmd.last);
101       t = cmd.first;
102       cmd.first = cmd.last;
103       cmd.last = t;
104     }
105   if (cmd.first < 1)
106     {
107       msg (SW, _("The first case (%ld) to list is less than 1.  The value is "
108            "being reset to 1."), cmd.first);
109       cmd.first = 1;
110     }
111   if (cmd.last < 1)
112     {
113       msg (SW, _("The last case (%ld) to list is less than 1.  The value is "
114            "being reset to 1."), cmd.last);
115       cmd.last = 1;
116     }
117   if (cmd.step < 1)
118     {
119       msg (SW, _("The step value %ld is less than 1.  The value is being "
120            "reset to 1."), cmd.step);
121       cmd.step = 1;
122     }
123
124   subcase_init_empty (&sc);
125   for (i = 0; i < cmd.n_variables; i++)
126     subcase_add_var (&sc, cmd.v_variables[i], SC_ASCEND);
127
128   grouper = casegrouper_create_splits (proc_open (ds), dict);
129   while (casegrouper_get_next_group (grouper, &group))
130     {
131       struct ccase *ccase;
132       struct table *t;
133
134       group = casereader_project (group, &sc);
135       if (cmd.numbering == LST_NUMBERED)
136         group = casereader_create_arithmetic_sequence (group, 1, 1);
137       group = casereader_select (group, cmd.first - 1,
138                                  (cmd.last != LONG_MAX ? cmd.last
139                                   : CASENUMBER_MAX), cmd.step);
140
141       ccase = casereader_peek (group, 0);
142       if (ccase != NULL)
143         {
144           output_split_file_values (ds, ccase);
145           case_unref (ccase);
146         }
147
148       if (cmd.numbering == LST_NUMBERED)
149         {
150           struct fmt_spec fmt;
151           size_t col;
152           int width;
153
154           width = cmd.last == LONG_MAX ? 5 : intlog10 (cmd.last);
155           fmt = fmt_for_output (FMT_F, width, 0);
156           col = caseproto_get_n_widths (casereader_get_proto (group)) - 1;
157
158           t = table_from_casereader (group, col, _("Case Number"), &fmt);
159         }
160       else
161         t = NULL;
162
163       for (i = 0; i < cmd.n_variables; i++)
164         {
165           const struct variable *var = cmd.v_variables[i];
166           struct table *c;
167
168           c = table_from_casereader (group, i, var_get_name (var),
169                                      var_get_print_format (var));
170           t = table_hpaste (t, c);
171         }
172
173       casereader_destroy (group);
174
175       table_item_submit (table_item_create (t, "Data List"));
176     }
177   ok = casegrouper_destroy (grouper);
178   ok = proc_commit (ds) && ok;
179
180   subcase_destroy (&sc);
181   free (cmd.v_variables);
182
183   return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
184 }
185
186 /*
187    Local Variables:
188    mode: c
189    End:
190 */