Move all command implementations into a single 'commands' directory.
[pspp] / src / language / data-io / save.c
diff --git a/src/language/data-io/save.c b/src/language/data-io/save.c
deleted file mode 100644 (file)
index a445870..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   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
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
-
-#include <config.h>
-
-#include <stdlib.h>
-
-#include "data/any-writer.h"
-#include "data/case-map.h"
-#include "data/case.h"
-#include "data/casereader.h"
-#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"
-#include "data/variable.h"
-#include "language/command.h"
-#include "language/data-io/file-handle.h"
-#include "language/data-io/trim.h"
-#include "language/lexer/lexer.h"
-#include "libpspp/assertion.h"
-#include "libpspp/compiler.h"
-#include "libpspp/message.h"
-
-#include "gl/xalloc.h"
-
-#include "gettext.h"
-#define _(msgid) gettext (msgid)
-
-/* Writing system and portable files. */
-
-/* Type of output file. */
-enum writer_type
-  {
-    SYSFILE_WRITER,     /* System file. */
-    PORFILE_WRITER      /* Portable file. */
-  };
-
-/* Type of a command. */
-enum command_type
-  {
-    XFORM_CMD,          /* Transformation. */
-    PROC_CMD            /* Procedure. */
-  };
-
-static int parse_output_proc (struct lexer *, struct dataset *,
-                              enum writer_type);
-static int parse_output_trns (struct lexer *, struct dataset *,
-                              enum writer_type);
-
-int
-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)
-{
-  return parse_output_proc (lexer, ds, PORFILE_WRITER);
-}
-
-int
-cmd_xsave (struct lexer *lexer, struct dataset *ds)
-{
-  return parse_output_trns (lexer, ds, SYSFILE_WRITER);
-}
-
-int
-cmd_xexport (struct lexer *lexer, struct dataset *ds)
-{
-  return parse_output_trns (lexer, ds, PORFILE_WRITER);
-}
-\f
-struct output_trns
-  {
-    struct casewriter *writer;          /* Writer. */
-  };
-
-static const struct trns_class output_trns_class;
-static struct casewriter *parse_write_command (struct lexer *,
-                                               struct dataset *,
-                                               enum writer_type,
-                                               enum command_type,
-                                               bool *retain_unselected);
-
-/* Parses and performs the SAVE or EXPORT procedure. */
-static int
-parse_output_proc (struct lexer *lexer, struct dataset *ds,
-                   enum writer_type writer_type)
-{
-  bool retain_unselected;
-  struct casewriter *output;
-  bool ok;
-
-  output = parse_write_command (lexer, ds, writer_type, PROC_CMD,
-                                &retain_unselected);
-  if (output == NULL)
-    return CMD_CASCADING_FAILURE;
-
-  casereader_transfer (proc_open_filtering (ds, !retain_unselected), output);
-  ok = casewriter_destroy (output);
-  ok = proc_commit (ds) && ok;
-
-  return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
-}
-
-/* Parses the XSAVE or XEXPORT transformation command. */
-static int
-parse_output_trns (struct lexer *lexer, struct dataset *ds, enum writer_type writer_type)
-{
-  struct output_trns *t = xmalloc (sizeof *t);
-  t->writer = parse_write_command (lexer, ds, writer_type, XFORM_CMD, NULL);
-  if (t->writer == NULL)
-    {
-      free (t);
-      return CMD_CASCADING_FAILURE;
-    }
-
-  add_transformation (ds, &output_trns_class, t);
-  return CMD_SUCCESS;
-}
-
-/* Parses SAVE or XSAVE or EXPORT or XEXPORT command.
-   WRITER_TYPE identifies the type of file to write,
-   and COMMAND_TYPE identifies the type of command.
-
-   On success, returns a writer.
-   For procedures only, sets *RETAIN_UNSELECTED to true if cases
-   that would otherwise be excluded by FILTER or USE should be
-   included.
-
-   On failure, returns a null pointer. */
-static struct casewriter *
-parse_write_command (struct lexer *lexer, struct dataset *ds,
-                    enum writer_type writer_type,
-                     enum command_type command_type,
-                     bool *retain_unselected)
-{
-  /* 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;
-  struct pfm_write_options porfile_opts;
-
-  assert (writer_type == SYSFILE_WRITER || writer_type == PORFILE_WRITER);
-  assert (command_type == XFORM_CMD || command_type == PROC_CMD);
-  assert ((retain_unselected != NULL) == (command_type == PROC_CMD));
-
-  if (command_type == PROC_CMD)
-    *retain_unselected = true;
-
-  handle = NULL;
-  metadata = NULL;
-  dict = dict_clone (dataset_dict (ds));
-  writer = NULL;
-  stage = NULL;
-  map = NULL;
-  sysfile_opts = sfm_writer_default_options ();
-  porfile_opts = pfm_writer_default_options ();
-
-  stage = case_map_stage_create (dict);
-  dict_delete_scratch_vars (dict);
-
-  lex_match (lexer, T_SLASH);
-  for (;;)
-    {
-      if (lex_match_id (lexer, "OUTFILE"))
-       {
-          if (handle != NULL)
-            {
-              lex_sbc_only_once (lexer, "OUTFILE");
-              goto error;
-            }
-
-         lex_match (lexer, T_EQUALS);
-
-         handle = fh_parse (lexer, FH_REF_FILE, NULL);
-         if (handle == NULL)
-           goto error;
-       }
-      else if (lex_match_id (lexer, "METADATA"))
-       {
-          if (metadata != NULL)
-            {
-              lex_sbc_only_once (lexer, "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. */
-        }
-      else if (lex_match_id (lexer, "PERMISSIONS"))
-        {
-          bool cw;
-
-          lex_match (lexer, T_EQUALS);
-          if (lex_match_id (lexer, "READONLY"))
-            cw = false;
-          else if (lex_match_id (lexer, "WRITEABLE"))
-            cw = true;
-          else
-            {
-              lex_error_expecting (lexer, "READONLY", "WRITEABLE");
-              goto error;
-            }
-          sysfile_opts.create_writeable = porfile_opts.create_writeable = cw;
-        }
-      else if (command_type == PROC_CMD && lex_match_id (lexer, "UNSELECTED"))
-        {
-          lex_match (lexer, T_EQUALS);
-          if (lex_match_id (lexer, "RETAIN"))
-            *retain_unselected = true;
-          else if (lex_match_id (lexer, "DELETE"))
-            *retain_unselected = false;
-          else
-            {
-              lex_error_expecting (lexer, "RETAIN", "DELETE");
-              goto error;
-            }
-        }
-      else if (writer_type == SYSFILE_WRITER
-               && lex_match_id (lexer, "COMPRESSED"))
-       sysfile_opts.compression = ANY_COMP_SIMPLE;
-      else if (writer_type == SYSFILE_WRITER
-               && lex_match_id (lexer, "UNCOMPRESSED"))
-       sysfile_opts.compression = ANY_COMP_NONE;
-      else if (writer_type == SYSFILE_WRITER
-               && lex_match_id (lexer, "ZCOMPRESSED"))
-       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_range (lexer, "VERSION", 2, 3))
-            goto error;
-          sysfile_opts.version = lex_integer (lexer);
-          lex_get (lexer);
-       }
-      else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "TYPE"))
-        {
-          lex_match (lexer, T_EQUALS);
-          if (lex_match_id (lexer, "COMMUNICATIONS"))
-            porfile_opts.type = PFM_COMM;
-          else if (lex_match_id (lexer, "TAPE"))
-            porfile_opts.type = PFM_TAPE;
-          else
-            {
-              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_range (lexer, "DIGITS", 1, INT_MAX))
-            goto error;
-          porfile_opts.digits = lex_integer (lexer);
-          lex_get (lexer);
-        }
-      else if (!parse_dict_trim (lexer, dict))
-        goto error;
-
-      if (!lex_match (lexer, T_SLASH))
-       break;
-    }
-  if (lex_end_of_command (lexer) != CMD_SUCCESS)
-    goto error;
-
-  if (!handle && !metadata)
-    {
-      msg (SE, _("The OUTFILE or METADATA subcommand is required."));
-      goto error;
-    }
-
-  dict_delete_scratch_vars (dict);
-  dict_compact_values (dict);
-
-  if (handle)
-    {
-      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)
-        {
-          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;
-    }
-
-  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_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_unref (dict);
-  case_map_destroy (map);
-  return NULL;
-}
-
-/* Writes case *C to the system file specified on XSAVE or XEXPORT. */
-static enum trns_result
-output_trns_proc (void *trns_, struct ccase **c, casenumber case_num UNUSED)
-{
-  struct output_trns *t = trns_;
-  casewriter_write (t->writer, case_ref (*c));
-  return TRNS_CONTINUE;
-}
-
-/* Frees an XSAVE or XEXPORT transformation.
-   Returns true if successful, false if an I/O error occurred. */
-static bool
-output_trns_free (void *trns_)
-{
-  struct output_trns *t = trns_;
-  bool ok = casewriter_destroy (t->writer);
-  free (t);
-  return ok;
-}
-
-static const struct trns_class output_trns_class = {
-  .name = "XSAVE/XEXPORT",
-  .execute = output_trns_proc,
-  .destroy = output_trns_free,
-};