char *encoding;
};
+struct write_file
+ {
+ struct file_handle *file;
+ struct dfm_writer *writer;
+ char *encoding;
+ };
+
struct matrix_state
{
struct dataset *dataset;
struct hmap vars;
bool in_loop;
struct file_handle *prev_save_outfile;
- struct file_handle *prev_write_outfile;
struct msave_common *common;
struct file_handle *prev_read_file;
struct read_file **read_files;
size_t n_read_files;
+
+ struct file_handle *prev_write_file;
+ struct write_file **write_files;
+ size_t n_write_files;
};
static struct matrix_var *
}
}
+static struct write_file *
+write_file_create (struct matrix_state *s, struct file_handle *fh)
+{
+ for (size_t i = 0; i < s->n_write_files; i++)
+ {
+ struct write_file *wf = s->write_files[i];
+ if (wf->file == fh)
+ {
+ fh_unref (fh);
+ return wf;
+ }
+ }
+
+ struct write_file *wf = xmalloc (sizeof *wf);
+ *wf = (struct write_file) { .file = fh };
+
+ s->write_files = xrealloc (s->write_files,
+ (s->n_write_files + 1) * sizeof *s->write_files);
+ s->write_files[s->n_write_files++] = wf;
+ return wf;
+}
+
+static struct dfm_writer *
+write_file_open (struct write_file *wf)
+{
+ if (!wf->writer)
+ wf->writer = dfm_open_writer (wf->file, wf->encoding);
+ return wf->writer;
+}
+
+static void
+write_file_destroy (struct write_file *wf)
+{
+ if (wf)
+ {
+ fh_unref (wf->file);
+ dfm_close_writer (wf->writer);
+ free (wf->encoding);
+ free (wf);
+ }
+}
+
static bool
matrix_parse_function (struct matrix_state *s, const char *token,
struct matrix_expr **exprp)
struct write_command
{
+ struct write_file *wf;
struct matrix_expr *expression;
- struct file_handle *outfile;
- char *encoding;
int c1, c2;
enum fmt_type format;
int w;
s->prev_read_file = fh_ref (fh);
read->rf = read_file_create (s, fh);
+ fh = NULL;
if (encoding)
{
free (read->rf->encoding);
.write = { .format = FMT_F },
};
+ struct file_handle *fh = NULL;
+ char *encoding = NULL;
struct write_command *write = &cmd->write;
write->expression = matrix_parse_exp (s);
if (!write->expression)
{
lex_match (s->lexer, T_EQUALS);
- fh_unref (write->outfile);
- write->outfile = fh_parse (s->lexer, FH_REF_FILE, NULL);
- if (!write->outfile)
+ fh_unref (fh);
+ fh = fh_parse (s->lexer, FH_REF_FILE, NULL);
+ if (!fh)
goto error;
}
else if (lex_match_id (s->lexer, "ENCODING"))
if (!lex_force_string (s->lexer))
goto error;
- free (write->encoding);
- write->encoding = ss_xstrdup (lex_tokss (s->lexer));
+ free (encoding);
+ encoding = ss_xstrdup (lex_tokss (s->lexer));
lex_get (s->lexer);
}
goto error;
}
- if (!write->outfile)
+ if (!fh)
{
- if (s->prev_write_outfile)
- write->outfile = fh_ref (s->prev_write_outfile);
+ if (s->prev_write_file)
+ fh = fh_ref (s->prev_write_file);
else
{
lex_sbc_missing ("OUTFILE");
goto error;
}
}
- fh_unref (s->prev_write_outfile);
- s->prev_write_outfile = fh_ref (write->outfile);
+ fh_unref (s->prev_write_file);
+ s->prev_write_file = fh_ref (fh);
+
+ write->wf = write_file_create (s, fh);
+ fh = NULL;
+ if (encoding)
+ {
+ free (write->wf->encoding);
+ write->wf->encoding = encoding;
+ encoding = NULL;
+ }
/* Field width may be specified in multiple ways:
return cmd;
error:
+ fh_unref (fh);
matrix_cmd_destroy (cmd);
return NULL;
}
return;
}
- struct dfm_writer *writer = dfm_open_writer (write->outfile, write->encoding);
+ struct dfm_writer *writer = write_file_open (write->wf);
if (!writer)
{
gsl_matrix_free (m);
case MCMD_WRITE:
matrix_expr_destroy (cmd->write.expression);
- free (cmd->write.encoding);
break;
case MCMD_GET:
}
hmap_destroy (&state.vars);
fh_unref (state.prev_save_outfile);
- fh_unref (state.prev_write_outfile);
if (state.common)
{
dict_unref (state.common->dict);
for (size_t i = 0; i < state.n_read_files; i++)
read_file_destroy (state.read_files[i]);
free (state.read_files);
+ fh_unref (state.prev_write_file);
+ for (size_t i = 0; i < state.n_write_files; i++)
+ write_file_destroy (state.write_files[i]);
+ free (state.write_files);
return CMD_SUCCESS;
}