X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fdata-io%2Fsave.c;h=88f3c75ee59a23d66a628995843d3b6dbaf23f27;hb=915ae62e6caddda59ac7c7b5e373fcb9b8da8a22;hp=7f1347db982a0292895e367cc0571aa3107c4c38;hpb=e2da62d735c597afeef2e0e9b36e5a4a83d7da94;p=pspp diff --git a/src/language/data-io/save.c b/src/language/data-io/save.c index 7f1347db98..88f3c75ee5 100644 --- a/src/language/data-io/save.c +++ b/src/language/data-io/save.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,6 +25,7 @@ #include "data/casewriter.h" #include "data/dataset.h" #include "data/dictionary.h" +#include "data/mdd-writer.h" #include "data/por-file-writer.h" #include "data/sys-file-writer.h" #include "data/transformations.h" @@ -35,6 +36,7 @@ #include "language/lexer/lexer.h" #include "libpspp/assertion.h" #include "libpspp/compiler.h" +#include "libpspp/message.h" #include "gl/xalloc.h" @@ -68,6 +70,12 @@ cmd_save (struct lexer *lexer, struct dataset *ds) return parse_output_proc (lexer, ds, SYSFILE_WRITER); } +int +cmd_save_data_collection (struct lexer *lexer, struct dataset *ds) +{ + return parse_output_proc (lexer, ds, SYSFILE_WRITER); +} + int cmd_export (struct lexer *lexer, struct dataset *ds) { @@ -91,8 +99,7 @@ struct output_trns struct casewriter *writer; /* Writer. */ }; -static trns_proc_func output_trns_proc; -static trns_free_func output_trns_free; +static const struct trns_class output_trns_class; static struct casewriter *parse_write_command (struct lexer *, struct dataset *, enum writer_type, @@ -132,7 +139,7 @@ parse_output_trns (struct lexer *lexer, struct dataset *ds, enum writer_type wri return CMD_CASCADING_FAILURE; } - add_transformation (ds, output_trns_proc, output_trns_free, t); + add_transformation (ds, &output_trns_class, t); return CMD_SUCCESS; } @@ -154,10 +161,12 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, { /* Common data. */ struct file_handle *handle; /* Output file. */ + struct file_handle *metadata; /* MDD output file. */ struct dictionary *dict; /* Dictionary for output file. */ struct casewriter *writer; /* Writer. */ struct case_map_stage *stage; /* Preparation for 'map'. */ struct case_map *map; /* Map from input data to data for writer. */ + const char *sav_name = ""; /* Common options. */ struct sfm_write_options sysfile_opts; @@ -171,6 +180,7 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, *retain_unselected = true; handle = NULL; + metadata = NULL; dict = dict_clone (dataset_dict (ds)); writer = NULL; stage = NULL; @@ -198,6 +208,20 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, if (handle == NULL) goto error; } + else if (lex_match_id (lexer, "METADATA")) + { + if (metadata != NULL) + { + lex_sbc_only_once ("METADATA"); + goto error; + } + + lex_match (lexer, T_EQUALS); + + metadata = fh_parse (lexer, FH_REF_FILE, NULL); + if (metadata == NULL) + goto error; + } else if (lex_match_id (lexer, "NAMES")) { /* Not yet implemented. */ @@ -213,8 +237,7 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, cw = true; else { - lex_error_expecting (lexer, "READONLY", "WRITEABLE", - NULL_SENTINEL); + lex_error_expecting (lexer, "READONLY", "WRITEABLE"); goto error; } sysfile_opts.create_writeable = porfile_opts.create_writeable = cw; @@ -228,24 +251,24 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, *retain_unselected = false; else { - lex_error_expecting (lexer, "RETAIN", "DELETE", NULL_SENTINEL); + lex_error_expecting (lexer, "RETAIN", "DELETE"); goto error; } } else if (writer_type == SYSFILE_WRITER && lex_match_id (lexer, "COMPRESSED")) - sysfile_opts.compression = SFM_COMP_SIMPLE; + sysfile_opts.compression = ANY_COMP_SIMPLE; else if (writer_type == SYSFILE_WRITER && lex_match_id (lexer, "UNCOMPRESSED")) - sysfile_opts.compression = SFM_COMP_NONE; + sysfile_opts.compression = ANY_COMP_NONE; else if (writer_type == SYSFILE_WRITER && lex_match_id (lexer, "ZCOMPRESSED")) - sysfile_opts.compression = SFM_COMP_ZLIB; + sysfile_opts.compression = ANY_COMP_ZLIB; else if (writer_type == SYSFILE_WRITER && lex_match_id (lexer, "VERSION")) { lex_match (lexer, T_EQUALS); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "VERSION", 2, 3)) goto error; sysfile_opts.version = lex_integer (lexer); lex_get (lexer); @@ -259,19 +282,19 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, porfile_opts.type = PFM_TAPE; else { - lex_error_expecting (lexer, "COMM", "TAPE", NULL_SENTINEL); + lex_error_expecting (lexer, "COMM", "TAPE"); goto error; } } else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "DIGITS")) { lex_match (lexer, T_EQUALS); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "DIGITS", 1, INT_MAX)) goto error; porfile_opts.digits = lex_integer (lexer); lex_get (lexer); } - else if (!parse_dict_trim (lexer, dict)) + else if (!parse_dict_trim (lexer, dict, false)) goto error; if (!lex_match (lexer, T_SLASH)) @@ -280,52 +303,67 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, if (lex_end_of_command (lexer) != CMD_SUCCESS) goto error; - if (handle == NULL) + if (!handle && !metadata) { - lex_sbc_missing ("OUTFILE"); + msg (SE, _("The OUTFILE or METADATA subcommand is required.")); goto error; } dict_delete_scratch_vars (dict); dict_compact_values (dict); - if (fh_get_referent (handle) == FH_REF_FILE) + if (handle) { - switch (writer_type) + if (metadata) + sav_name = (fh_get_referent (handle) == FH_REF_FILE + ? fh_get_file_name (handle) + : fh_get_name (handle)); + if (fh_get_referent (handle) == FH_REF_FILE) { - case SYSFILE_WRITER: - writer = sfm_open_writer (handle, dict, sysfile_opts); - break; - case PORFILE_WRITER: - writer = pfm_open_writer (handle, dict, porfile_opts); - break; + switch (writer_type) + { + case SYSFILE_WRITER: + writer = sfm_open_writer (handle, dict, sysfile_opts); + break; + case PORFILE_WRITER: + writer = pfm_open_writer (handle, dict, porfile_opts); + break; + } } + else + writer = any_writer_open (handle, dict); + if (writer == NULL) + goto error; + } + + if (metadata) + { + if (!mdd_write (metadata, dict, sav_name)) + goto error; } - else - writer = any_writer_open (handle, dict); - if (writer == NULL) - goto error; map = case_map_stage_get_case_map (stage); case_map_stage_destroy (stage); if (map != NULL) writer = case_map_create_output_translator (map, writer); - dict_destroy (dict); + dict_unref (dict); fh_unref (handle); + fh_unref (metadata); return writer; error: case_map_stage_destroy (stage); fh_unref (handle); + fh_unref (metadata); casewriter_destroy (writer); - dict_destroy (dict); + dict_unref (dict); case_map_destroy (map); return NULL; } /* Writes case *C to the system file specified on XSAVE or XEXPORT. */ -static int +static enum trns_result output_trns_proc (void *trns_, struct ccase **c, casenumber case_num UNUSED) { struct output_trns *t = trns_; @@ -343,3 +381,9 @@ output_trns_free (void *trns_) free (t); return ok; } + +static const struct trns_class output_trns_class = { + .name = "XSAVE/XEXPORT", + .execute = output_trns_proc, + .destroy = output_trns_free, +};