1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2010 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/>. */
21 #include "data/case-map.h"
22 #include "data/casereader.h"
23 #include "data/casewriter.h"
24 #include "data/csv-file-writer.h"
25 #include "data/dictionary.h"
26 #include "data/file-name.h"
27 #include "data/format.h"
28 #include "data/procedure.h"
29 #include "data/settings.h"
30 #include "language/command.h"
31 #include "language/data-io/file-handle.h"
32 #include "language/data-io/trim.h"
33 #include "language/lexer/lexer.h"
34 #include "libpspp/message.h"
39 #define _(msgid) gettext (msgid)
40 #define N_(msgid) (msgid)
43 cmd_save_translate (struct lexer *lexer, struct dataset *ds)
45 enum { CSV_FILE = 1, TAB_FILE } type;
47 struct dictionary *dict;
49 struct casewriter *writer;
50 struct file_handle *handle;
52 struct csv_writer_options csv_opts;
56 bool retain_unselected;
57 bool recode_user_missing;
58 bool include_var_names;
59 bool use_value_labels;
60 bool use_print_formats;
69 dict = dict_clone (dataset_dict (ds));
75 retain_unselected = true;
76 recode_user_missing = false;
77 include_var_names = false;
78 use_value_labels = false;
79 use_print_formats = false;
80 decimal = settings_get_decimal_char (FMT_F);
84 case_map_prepare_dict (dict);
85 dict_delete_scratch_vars (dict);
87 while (lex_match (lexer, T_SLASH))
89 if (lex_match_id (lexer, "OUTFILE"))
93 lex_sbc_only_once ("OUTFILE");
97 lex_match (lexer, T_EQUALS);
99 handle = fh_parse (lexer, FH_REF_FILE);
103 else if (lex_match_id (lexer, "TYPE"))
107 lex_sbc_only_once ("TYPE");
111 lex_match (lexer, T_EQUALS);
112 if (lex_match_id (lexer, "CSV"))
114 else if (lex_match_id (lexer, "TAB"))
118 lex_error (lexer, _("expecting %s or %s"), "CSV", "TAB");
122 else if (lex_match_id (lexer, "REPLACE"))
124 else if (lex_match_id (lexer, "FIELDNAMES"))
125 include_var_names = true;
126 else if (lex_match_id (lexer, "MISSING"))
128 lex_match (lexer, T_EQUALS);
129 if (lex_match_id (lexer, "IGNORE"))
130 recode_user_missing = false;
131 else if (lex_match_id (lexer, "RECODE"))
132 recode_user_missing = true;
135 lex_error (lexer, _("expecting %s or %s"), "IGNORE", "RECODE");
139 else if (lex_match_id (lexer, "CELLS"))
141 lex_match (lexer, T_EQUALS);
142 if (lex_match_id (lexer, "VALUES"))
143 use_value_labels = false;
144 else if (lex_match_id (lexer, "LABELS"))
145 use_value_labels = true;
148 lex_error (lexer, _("expecting %s or %s"), "VALUES", "LABELS");
152 else if (lex_match_id (lexer, "TEXTOPTIONS"))
154 lex_match (lexer, T_EQUALS);
157 if (lex_match_id (lexer, "DELIMITER"))
159 lex_match (lexer, T_EQUALS);
160 if (!lex_force_string (lexer))
162 if (ds_length (lex_tokstr (lexer)) != 1)
164 msg (SE, _("The %s string must contain exactly one "
165 "character."), "DELIMITER");
168 delimiter = ds_first (lex_tokstr (lexer));
171 else if (lex_match_id (lexer, "QUALIFIER"))
173 lex_match (lexer, T_EQUALS);
174 if (!lex_force_string (lexer))
176 if (ds_length (lex_tokstr (lexer)) != 1)
178 msg (SE, _("The %s string must contain exactly one "
179 "character."), "QUALIFIER");
182 qualifier = ds_first (lex_tokstr (lexer));
185 else if (lex_match_id (lexer, "DECIMAL"))
187 lex_match (lexer, T_EQUALS);
188 if (lex_match_id (lexer, "DOT"))
190 else if (lex_match_id (lexer, "COMMA"))
194 lex_error (lexer, _("expecting %s or %s"),
199 else if (lex_match_id (lexer, "FORMAT"))
201 lex_match (lexer, T_EQUALS);
202 if (lex_match_id (lexer, "PLAIN"))
203 use_print_formats = false;
204 else if (lex_match_id (lexer, "VARIABLE"))
205 use_print_formats = true;
208 lex_error (lexer, _("expecting %s or %s"),
209 "PLAIN", "VARIABLE");
217 else if (lex_match_id (lexer, "UNSELECTED"))
219 lex_match (lexer, T_EQUALS);
220 if (lex_match_id (lexer, "RETAIN"))
221 retain_unselected = true;
222 else if (lex_match_id (lexer, "DELETE"))
223 retain_unselected = false;
226 lex_error (lexer, _("expecting %s or %s"), "RETAIN", "DELETE");
230 else if (!parse_dict_trim (lexer, dict))
233 if (lex_end_of_command (lexer) != CMD_SUCCESS)
238 lex_sbc_missing (lexer, "TYPE");
241 else if (handle == NULL)
243 lex_sbc_missing (lexer, "OUTFILE");
246 else if (!replace && fn_exists (fh_get_file_name (handle)))
248 msg (SE, _("Output file `%s' exists but REPLACE was not specified."),
249 fh_get_file_name (handle));
253 dict_delete_scratch_vars (dict);
254 dict_compact_values (dict);
256 csv_opts.recode_user_missing = recode_user_missing;
257 csv_opts.include_var_names = include_var_names;
258 csv_opts.use_value_labels = use_value_labels;
259 csv_opts.use_print_formats = use_print_formats;
260 csv_opts.decimal = decimal;
261 csv_opts.delimiter = (delimiter ? delimiter
262 : type == TAB_FILE ? '\t'
263 : decimal == '.' ? ','
265 csv_opts.qualifier = qualifier;
267 writer = csv_writer_open (handle, dict, &csv_opts);
272 map = case_map_from_dict (dict);
274 writer = case_map_create_output_translator (map, writer);
277 casereader_transfer (proc_open_filtering (ds, !retain_unselected), writer);
278 ok = casewriter_destroy (writer);
279 ok = proc_commit (ds) && ok;
281 return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
286 case_map_destroy (map);