1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2007, 2008, 2009 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/any-writer.h>
22 #include <data/case-map.h>
23 #include <data/case.h>
24 #include <data/casereader.h>
25 #include <data/casewriter.h>
26 #include <data/dictionary.h>
27 #include <data/por-file-writer.h>
28 #include <data/procedure.h>
29 #include <data/sys-file-writer.h>
30 #include <data/transformations.h>
31 #include <data/variable.h>
32 #include <language/command.h>
33 #include <language/data-io/file-handle.h>
34 #include <language/data-io/trim.h>
35 #include <language/lexer/lexer.h>
36 #include <libpspp/assertion.h>
37 #include <libpspp/compiler.h>
42 #define _(msgid) gettext (msgid)
44 /* Writing system and portable files. */
46 /* Type of output file. */
49 SYSFILE_WRITER, /* System file. */
50 PORFILE_WRITER /* Portable file. */
53 /* Type of a command. */
56 XFORM_CMD, /* Transformation. */
57 PROC_CMD /* Procedure. */
60 static int parse_output_proc (struct lexer *, struct dataset *,
62 static int parse_output_trns (struct lexer *, struct dataset *,
66 cmd_save (struct lexer *lexer, struct dataset *ds)
68 return parse_output_proc (lexer, ds, SYSFILE_WRITER);
72 cmd_export (struct lexer *lexer, struct dataset *ds)
74 return parse_output_proc (lexer, ds, PORFILE_WRITER);
78 cmd_xsave (struct lexer *lexer, struct dataset *ds)
80 return parse_output_trns (lexer, ds, SYSFILE_WRITER);
84 cmd_xexport (struct lexer *lexer, struct dataset *ds)
86 return parse_output_trns (lexer, ds, PORFILE_WRITER);
91 struct casewriter *writer; /* Writer. */
94 static trns_proc_func output_trns_proc;
95 static trns_free_func output_trns_free;
96 static struct casewriter *parse_write_command (struct lexer *,
100 bool *retain_unselected);
102 /* Parses and performs the SAVE or EXPORT procedure. */
104 parse_output_proc (struct lexer *lexer, struct dataset *ds,
105 enum writer_type writer_type)
107 bool retain_unselected;
108 struct variable *saved_filter_variable;
109 struct casewriter *output;
112 output = parse_write_command (lexer, ds, writer_type, PROC_CMD,
115 return CMD_CASCADING_FAILURE;
117 saved_filter_variable = dict_get_filter (dataset_dict (ds));
118 if (retain_unselected)
119 dict_set_filter (dataset_dict (ds), NULL);
121 casereader_transfer (proc_open (ds), output);
122 ok = casewriter_destroy (output);
123 ok = proc_commit (ds) && ok;
125 dict_set_filter (dataset_dict (ds), saved_filter_variable);
127 return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
130 /* Parses the XSAVE or XEXPORT transformation command. */
132 parse_output_trns (struct lexer *lexer, struct dataset *ds, enum writer_type writer_type)
134 struct output_trns *t = xmalloc (sizeof *t);
135 t->writer = parse_write_command (lexer, ds, writer_type, XFORM_CMD, NULL);
136 if (t->writer == NULL)
139 return CMD_CASCADING_FAILURE;
142 add_transformation (ds, output_trns_proc, output_trns_free, t);
146 /* Parses SAVE or XSAVE or EXPORT or XEXPORT command.
147 WRITER_TYPE identifies the type of file to write,
148 and COMMAND_TYPE identifies the type of command.
150 On success, returns a writer.
151 For procedures only, sets *RETAIN_UNSELECTED to true if cases
152 that would otherwise be excluded by FILTER or USE should be
155 On failure, returns a null pointer. */
156 static struct casewriter *
157 parse_write_command (struct lexer *lexer, struct dataset *ds,
158 enum writer_type writer_type,
159 enum command_type command_type,
160 bool *retain_unselected)
163 struct file_handle *handle; /* Output file. */
164 struct dictionary *dict; /* Dictionary for output file. */
165 struct casewriter *writer; /* Writer. */
166 struct case_map *map; /* Map from input data to data for writer. */
168 /* Common options. */
169 bool print_map; /* Print map? TODO. */
170 bool print_short_names; /* Print long-to-short name map. TODO. */
171 struct sfm_write_options sysfile_opts;
172 struct pfm_write_options porfile_opts;
174 assert (writer_type == SYSFILE_WRITER || writer_type == PORFILE_WRITER);
175 assert (command_type == XFORM_CMD || command_type == PROC_CMD);
176 assert ((retain_unselected != NULL) == (command_type == PROC_CMD));
178 if (command_type == PROC_CMD)
179 *retain_unselected = true;
182 dict = dict_clone (dataset_dict (ds));
186 print_short_names = false;
187 sysfile_opts = sfm_writer_default_options ();
188 porfile_opts = pfm_writer_default_options ();
190 case_map_prepare_dict (dict);
191 dict_delete_scratch_vars (dict);
193 lex_match (lexer, '/');
196 if (lex_match_id (lexer, "OUTFILE"))
200 lex_sbc_only_once ("OUTFILE");
204 lex_match (lexer, '=');
206 handle = fh_parse (lexer, FH_REF_FILE | FH_REF_SCRATCH);
210 else if (lex_match_id (lexer, "NAMES"))
211 print_short_names = true;
212 else if (lex_match_id (lexer, "PERMISSIONS"))
216 lex_match (lexer, '=');
217 if (lex_match_id (lexer, "READONLY"))
219 else if (lex_match_id (lexer, "WRITEABLE"))
223 lex_error (lexer, _("expecting %s or %s"),
224 "READONLY", "WRITEABLE");
227 sysfile_opts.create_writeable = porfile_opts.create_writeable = cw;
229 else if (command_type == PROC_CMD && lex_match_id (lexer, "UNSELECTED"))
231 lex_match (lexer, '=');
232 if (lex_match_id (lexer, "RETAIN"))
233 *retain_unselected = true;
234 else if (lex_match_id (lexer, "DELETE"))
235 *retain_unselected = false;
238 lex_error (lexer, _("expecting %s or %s"), "RETAIN", "DELETE");
242 else if (writer_type == SYSFILE_WRITER
243 && lex_match_id (lexer, "COMPRESSED"))
244 sysfile_opts.compress = true;
245 else if (writer_type == SYSFILE_WRITER
246 && lex_match_id (lexer, "UNCOMPRESSED"))
247 sysfile_opts.compress = false;
248 else if (writer_type == SYSFILE_WRITER
249 && lex_match_id (lexer, "VERSION"))
251 lex_match (lexer, '=');
252 if (!lex_force_int (lexer))
254 sysfile_opts.version = lex_integer (lexer);
257 else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "TYPE"))
259 lex_match (lexer, '=');
260 if (lex_match_id (lexer, "COMMUNICATIONS"))
261 porfile_opts.type = PFM_COMM;
262 else if (lex_match_id (lexer, "TAPE"))
263 porfile_opts.type = PFM_TAPE;
266 lex_error (lexer, _("expecting %s or %s"), "COMM", "TAPE");
270 else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "DIGITS"))
272 lex_match (lexer, '=');
273 if (!lex_force_int (lexer))
275 porfile_opts.digits = lex_integer (lexer);
278 else if (!parse_dict_trim (lexer, dict))
281 if (!lex_match (lexer, '/'))
284 if (lex_end_of_command (lexer) != CMD_SUCCESS)
289 lex_sbc_missing (lexer, "OUTFILE");
293 dict_delete_scratch_vars (dict);
294 dict_compact_values (dict);
296 if (fh_get_referent (handle) == FH_REF_FILE)
301 writer = sfm_open_writer (handle, dict, sysfile_opts);
304 writer = pfm_open_writer (handle, dict, porfile_opts);
309 writer = any_writer_open (handle, dict);
313 map = case_map_from_dict (dict);
315 writer = case_map_create_output_translator (map, writer);
323 casewriter_destroy (writer);
325 case_map_destroy (map);
329 /* Writes case *C to the system file specified on XSAVE or XEXPORT. */
331 output_trns_proc (void *trns_, struct ccase **c, casenumber case_num UNUSED)
333 struct output_trns *t = trns_;
334 casewriter_write (t->writer, case_ref (*c));
335 return TRNS_CONTINUE;
338 /* Frees an XSAVE or XEXPORT transformation.
339 Returns true if successful, false if an I/O error occurred. */
341 output_trns_free (void *trns_)
343 struct output_trns *t = trns_;
344 bool ok = casewriter_destroy (t->writer);