1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2009-2011, 2013, 2014, 2016 Free Software Foundation, Inc.
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.
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.
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/>. */
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 "language/lexer/variable-parser.h"
35 #include "libpspp/compiler.h"
36 #include "libpspp/ll.h"
37 #include "libpspp/message.h"
38 #include "libpspp/misc.h"
39 #include "output/tab.h"
40 #include "output/table-item.h"
42 #include "gl/intprops.h"
43 #include "gl/minmax.h"
44 #include "gl/xalloc.h"
45 #include "gl/xmalloca.h"
48 #define _(msgid) gettext (msgid)
62 const struct variable
**v_variables
;
64 enum numbering numbering
;
69 list_execute (const struct lst_cmd
*lcmd
, struct dataset
*ds
)
71 const struct dictionary
*dict
= dataset_dict (ds
);
75 struct casegrouper
*grouper
;
76 struct casereader
*group
;
79 subcase_init_empty (&sc
);
80 for (i
= 0; i
< lcmd
->n_variables
; i
++)
81 subcase_add_var (&sc
, lcmd
->v_variables
[i
], SC_ASCEND
);
84 grouper
= casegrouper_create_splits (proc_open (ds
), dict
);
85 while (casegrouper_get_next_group (grouper
, &group
))
90 ccase
= casereader_peek (group
, 0);
93 output_split_file_values (ds
, ccase
);
97 group
= casereader_project (group
, &sc
);
98 if (lcmd
->numbering
== format_numbered
)
99 group
= casereader_create_arithmetic_sequence (group
, 1, 1);
100 group
= casereader_select (group
, lcmd
->first
- 1,
101 (lcmd
->last
!= LONG_MAX
? lcmd
->last
102 : CASENUMBER_MAX
), lcmd
->step
);
104 if (lcmd
->numbering
== format_numbered
)
110 width
= lcmd
->last
== LONG_MAX
? 5 : intlog10 (lcmd
->last
);
111 fmt
= fmt_for_output (FMT_F
, width
, 0);
112 col
= caseproto_get_n_widths (casereader_get_proto (group
)) - 1;
114 t
= table_from_casereader (group
, col
, _("Case Number"), &fmt
);
119 for (i
= 0; i
< lcmd
->n_variables
; i
++)
121 const struct variable
*var
= lcmd
->v_variables
[i
];
124 c
= table_from_casereader (group
, i
, var_get_name (var
),
125 var_get_print_format (var
));
126 t
= table_hpaste (t
, c
);
129 casereader_destroy (group
);
131 table_item_submit (table_item_create (t
, "Data List", NULL
));
133 ok
= casegrouper_destroy (grouper
);
134 ok
= proc_commit (ds
) && ok
;
136 subcase_destroy (&sc
);
137 free (lcmd
->v_variables
);
139 return ok
? CMD_SUCCESS
: CMD_CASCADING_FAILURE
;
143 /* Parses and executes the LIST procedure. */
145 cmd_list (struct lexer
*lexer
, struct dataset
*ds
)
148 const struct dictionary
*dict
= dataset_dict (ds
);
150 /* Fill in defaults. */
155 cmd
.v_variables
= NULL
;
156 cmd
.numbering
= format_unnumbered
;
159 while (lex_token (lexer
) != T_ENDCMD
)
161 lex_match (lexer
, T_SLASH
);
162 if (lex_match_id (lexer
, "VARIABLES") )
164 lex_match (lexer
, T_EQUALS
);
165 if (! parse_variables_const (lexer
, dict
, &cmd
.v_variables
, &cmd
.n_variables
, 0 ))
167 msg (SE
, _("No variables specified."));
171 else if (lex_match_id (lexer
, "FORMAT") )
173 lex_match (lexer
, T_EQUALS
);
174 if (lex_match_id (lexer
, "NUMBERED") )
176 cmd
.numbering
= format_numbered
;
178 else if (lex_match_id (lexer
, "UNNUMBERED") )
180 cmd
.numbering
= format_unnumbered
;
184 lex_error (lexer
, NULL
);
188 /* example: LIST /CASES=FROM 1 TO 25 BY 5. */
189 else if (lex_match_id (lexer
, "CASES"))
191 lex_match (lexer
, T_EQUALS
);
192 if (lex_match_id (lexer
, "FROM") && lex_force_int (lexer
))
194 cmd
.first
= lex_integer (lexer
);
198 if ((lex_match (lexer
, T_TO
) && lex_force_int (lexer
))
199 || lex_is_integer (lexer
))
201 cmd
.last
= lex_integer (lexer
);
205 if (lex_match (lexer
, T_BY
) && lex_force_int (lexer
))
207 cmd
.step
= lex_integer (lexer
);
211 else if (! parse_variables_const (lexer
, dict
, &cmd
.v_variables
, &cmd
.n_variables
, 0 ))
218 /* Verify arguments. */
219 if (cmd
.first
> cmd
.last
)
222 msg (SW
, _("The first case (%ld) specified precedes the last case (%ld) "
223 "specified. The values will be swapped."), cmd
.first
, cmd
.last
);
225 cmd
.first
= cmd
.last
;
231 msg (SW
, _("The first case (%ld) to list is less than 1. The value is "
232 "being reset to 1."), cmd
.first
);
238 msg (SW
, _("The last case (%ld) to list is less than 1. The value is "
239 "being reset to 1."), cmd
.last
);
245 msg (SW
, _("The step value %ld is less than 1. The value is being "
246 "reset to 1."), cmd
.step
);
250 /* If no variables were explicitly provided, then default to ALL */
251 if (cmd
.n_variables
== 0)
252 dict_get_vars (dict
, &cmd
.v_variables
, &cmd
.n_variables
,
253 DC_SYSTEM
| DC_SCRATCH
);
255 return list_execute (&cmd
, ds
);
258 free (cmd
.v_variables
);