예제 #1
0
/* Closes reader R opened by dfm_open_reader(). */
void
dfm_close_reader (struct dfm_reader *r)
{
  if (r == NULL)
    return;

  if (fh_unlock (r->lock))
    {
      /* File is still locked by another client. */
      return;
    }

  /* This was the last client, so close the underlying file. */
  if (fh_get_referent (r->fh) != FH_REF_INLINE)
    fn_close (fh_get_file_name (r->fh), r->file);
  else
    {
      /* Skip any remaining data on the inline file. */
      if (r->flags & DFM_SAW_BEGIN_DATA)
        {
          dfm_reread_record (r, 0);
          while (!dfm_eof (r))
            dfm_forward_record (r);
        }
    }

  fh_unref (r->fh);
  ds_destroy (&r->line);
  ds_destroy (&r->scratch);
  free (r);
}
예제 #2
0
const char *
dfm_get_file_name (const struct dfm_reader *r)
{
  return (fh_get_referent (r->fh) == FH_REF_FILE
          ? fh_get_file_name (r->fh)
          : NULL);
}
예제 #3
0
/* Reads a record from R, setting the current position to the
   start of the line.  If an error occurs or end-of-file is
   encountered, the current line is set to null. */
static bool
read_record (struct dfm_reader *r)
{
  if (fh_get_referent (r->fh) == FH_REF_FILE)
    {
      bool ok = read_file_record (r);
      if (ok)
        r->line_number++;
      return ok;
    }
  else
    return read_inline_record (r);
}
예제 #4
0
/* Opens the file designated by file handle FH for reading as a
   data file.  Providing fh_inline_file() for FH designates the
   "inline file", that is, data included inline in the command
   file between BEGIN FILE and END FILE.  Returns a reader if
   successful, or a null pointer otherwise. */
struct dfm_reader *
dfm_open_reader (struct file_handle *fh, struct lexer *lexer)
{
  struct dfm_reader *r;
  struct fh_lock *lock;

  /* TRANSLATORS: this fragment will be interpolated into
     messages in fh_lock() that identify types of files. */
  lock = fh_lock (fh, FH_REF_FILE | FH_REF_INLINE, N_("data file"),
                  FH_ACC_READ, false);
  if (lock == NULL)
    return NULL;

  r = fh_lock_get_aux (lock);
  if (r != NULL)
    return r;

  r = xmalloc (sizeof *r);
  r->fh = fh_ref (fh);
  r->lock = lock;
  r->lexer = lexer;
  ds_init_empty (&r->line);
  ds_init_empty (&r->scratch);
  r->flags = DFM_ADVANCE;
  r->eof_cnt = 0;
  r->block_left = 0;
  if (fh_get_referent (fh) != FH_REF_INLINE)
    {
      struct stat s;
      r->line_number = 0;
      r->file = fn_open (fh_get_file_name (fh), "rb");
      if (r->file == NULL)
        {
          msg (ME, _("Could not open `%s' for reading as a data file: %s."),
               fh_get_file_name (r->fh), strerror (errno));
          fh_unlock (r->lock);
          fh_unref (fh);
          free (r);
          return NULL;
        }
      r->file_size = fstat (fileno (r->file), &s) == 0 ? s.st_size : -1;
    }
  else
    r->file_size = -1;
  fh_lock_set_aux (lock, r);

  return r;
}
예제 #5
0
파일: any-reader.c 프로젝트: student-t/PSPP
/* Returns a casereader for HANDLE.  On success, returns the new
   casereader and stores the file's dictionary into *DICT.  On
   failure, returns a null pointer.

   Ordinarily the reader attempts to automatically detect the character
   encoding based on the file's contents.  This isn't always possible,
   especially for files written by old versions of SPSS or PSPP, so specifying
   a nonnull ENCODING overrides the choice of character encoding.  */
struct casereader *
any_reader_open (struct file_handle *handle, const char *encoding,
                 struct dictionary **dict)
{
  switch (fh_get_referent (handle))
    {
    case FH_REF_FILE:
      {
        enum detect_result result;

        result = try_detect (fh_get_file_name (handle), sfm_detect);
        if (result == ANY_ERROR)
          return NULL;
        else if (result == ANY_YES)
          {
            struct sfm_reader *r;

            r = sfm_open (handle);
            if (r == NULL)
              return NULL;

            return sfm_decode (r, encoding, dict, NULL);
          }

        result = try_detect (fh_get_file_name (handle), pfm_detect);
        if (result == ANY_ERROR)
          return NULL;
        else if (result == ANY_YES)
          return pfm_open_reader (handle, dict, NULL);

        msg (SE, _("`%s' is not a system or portable file."),
             fh_get_file_name (handle));
        return NULL;
      }

    case FH_REF_INLINE:
      msg (SE, _("The inline file is not allowed here."));
      return NULL;

    case FH_REF_DATASET:
      return dataset_reader_open (handle, dict);
    }
  NOT_REACHED ();
}
예제 #6
0
int
dfm_get_line_number (const struct dfm_reader *r)
{
  return fh_get_referent (r->fh) == FH_REF_FILE ? r->line_number : -1;
}
예제 #7
0
/* Returns true if an I/O error occurred on READER, false otherwise. */
bool
dfm_reader_error (const struct dfm_reader *r)
{
  return fh_get_referent (r->fh) == FH_REF_FILE && ferror (r->file);
}
예제 #8
0
파일: save.c 프로젝트: RobertDash/pspp
/* 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 dictionary *dict;    /* Dictionary for output file. */
  struct casewriter *writer;  /* Writer. */
  struct case_map *map;       /* Map from input data to data for writer. */

  /* Common options. */
  bool print_map;             /* Print map?  TODO. */
  bool print_short_names;     /* Print long-to-short name map.  TODO. */
  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;
  dict = dict_clone (dataset_dict (ds));
  writer = NULL;
  map = NULL;
  print_map = false;
  print_short_names = false;
  sysfile_opts = sfm_writer_default_options ();
  porfile_opts = pfm_writer_default_options ();

  case_map_prepare_dict (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 ("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, "NAMES"))
        print_short_names = true;
      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",
                                   NULL_SENTINEL);
              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", NULL_SENTINEL);
              goto error;
            }
        }
      else if (writer_type == SYSFILE_WRITER
               && lex_match_id (lexer, "COMPRESSED"))
	sysfile_opts.compress = true;
      else if (writer_type == SYSFILE_WRITER
               && lex_match_id (lexer, "UNCOMPRESSED"))
	sysfile_opts.compress = false;
      else if (writer_type == SYSFILE_WRITER
               && lex_match_id (lexer, "VERSION"))
	{
	  lex_match (lexer, T_EQUALS);
	  if (!lex_force_int (lexer))
            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", NULL_SENTINEL);
              goto error;
            }
        }
      else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "DIGITS"))
        {
          lex_match (lexer, T_EQUALS);
          if (!lex_force_int (lexer))
            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 == NULL)
    {
      lex_sbc_missing ("OUTFILE");
      goto error;
    }

  dict_delete_scratch_vars (dict);
  dict_compact_values (dict);

  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;

  map = case_map_from_dict (dict);
  if (map != NULL)
    writer = case_map_create_output_translator (map, writer);
  dict_destroy (dict);

  fh_unref (handle);
  return writer;

 error:
  fh_unref (handle);
  casewriter_destroy (writer);
  dict_destroy (dict);
  case_map_destroy (map);
  return NULL;
}