/* addendum to session.c, for handling the saving of session info to
an XML file, and the re-building of a session from same.
*/
#include "usermat.h"
static int check_graph_file (const char *fname)
{
char fullname[MAXLEN];
FILE *fp;
int err = 0;
session_file_make_path(fullname, fname);
fp = gretl_fopen(fullname, "r");
if (fp == NULL) {
errbox(_("Warning: couldn't open graph file %s"), fname);
err = 1;
} else {
fclose(fp);
}
return err;
}
static int restore_session_graphs (xmlNodePtr node)
{
xmlNodePtr cur;
int i = 0;
int inpage = 0;
int err = 0;
/* reset prior to parsing */
session.ngraphs = 0;
cur = node->xmlChildrenNode;
while (cur != NULL && !err) {
xmlChar *name = NULL;
xmlChar *fname = NULL;
int type, ID;
name = xmlGetProp(cur, (XUC) "name");
if (name == NULL) {
err = 1;
}
if (!err) {
fname = xmlGetProp(cur, (XUC) "fname");
if (fname == NULL) {
err = 1;
} else {
err = check_graph_file((const char *) fname);
}
}
if (!err && (!gretl_xml_get_prop_as_int(cur, "ID", &ID) ||
!gretl_xml_get_prop_as_int(cur, "type", &type))) {
err = 1;
}
if (!err) {
SESSION_GRAPH *sg;
sg = session_append_graph((const char *) name,
(const char *) fname,
type);
err = (sg == NULL);
}
if (!err) {
if (gretl_xml_get_prop_as_int(cur, "inpage", &inpage)) {
graph_page_add_file((const char *) fname); /* FIXME path? */
}
}
free(name);
free(fname);
cur = cur->next;
i++;
}
return err;
}
static int restore_session_texts (xmlNodePtr node, xmlDocPtr doc)
{
xmlNodePtr cur;
int i = 0;
int err = 0;
session.ntexts = 0;
cur = node->xmlChildrenNode;
while (cur != NULL && !err) {
xmlChar *name = NULL;
xmlChar *buf = NULL;
name = xmlGetProp(cur, (XUC) "name");
if (name == NULL) {
err = 1;
} else {
buf = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
if (buf == NULL) {
err = 1;
} else {
err = session_append_text((const char *) name,
(char *) buf);
}
}
free(name);
cur = cur->next;
i++;
}
return err;
}
static int data_submask_from_xml (xmlNodePtr node, xmlDocPtr doc,
struct sample_info *sinfo)
{
char *mask;
int mode, err;
err = gretl_xml_get_submask(node, doc, &mask, &mode);
if (!err) {
sinfo->mask = mask;
sinfo->mode = mode;
}
return err;
}
static gpointer rebuild_session_model (const char *fname,
GretlObjType type,
SavedObjectFlags *flags,
int *err)
{
gpointer ptr = NULL;
xmlDocPtr doc;
xmlNodePtr node;
*err = gretl_xml_open_doc_root(fname,
(type == GRETL_OBJ_EQN)? "gretl-model" :
(type == GRETL_OBJ_VAR)? "gretl-VAR" :
"gretl-equation-system", &doc, &node);
if (*err) {
return NULL;
}
if (!gretl_xml_get_prop_as_int(node, "saveflags", (int *) flags)) {
*flags = IN_GUI_SESSION;
}
if (type == GRETL_OBJ_EQN) {
ptr = gretl_model_from_XML(node, doc, err);
} else if (type == GRETL_OBJ_VAR) {
ptr = gretl_VAR_from_XML(node, doc, err);
} else {
ptr = gretl_system_from_XML(node, doc, err);
}
xmlFreeDoc(doc);
if (ptr != NULL) {
gretl_object_ref(ptr, type); /* FIXME do this later? */
}
/* need to clean up on error here (also: clean up XML parser?) */
return ptr;
}
static int
reattach_model (void *ptr, GretlObjType type, const char *name,
SavedObjectFlags flags)
{
int err = 0;
if (flags & IN_GUI_SESSION) {
SESSION_MODEL *smod;
smod = session_model_new(ptr, name, type);
if (smod == NULL) {
err = E_ALLOC;
} else {
err = session_append_model(smod);
}
}
if (!err && (flags & IN_MODEL_TABLE)) {
err = add_to_model_table(ptr, MODEL_ADD_BY_CMD, NULL);
}
if (!err && (flags & IN_NAMED_STACK)) {
err = gretl_stack_object(ptr, type);
}
if (!err && (flags & IS_LAST_MODEL)) {
set_as_last_model(ptr, type);
}
return err;
}
static int restore_session_models (xmlNodePtr node, xmlDocPtr doc)
{
char fullname[MAXLEN];
xmlNodePtr cur;
int i, err = 0;
/* reset prior to parsing */
session.nmodels = 0;
cur = node->xmlChildrenNode;
i = 0;
while (cur != NULL && !err) {
SavedObjectFlags flags;
xmlChar *fname = NULL;
xmlChar *name = NULL;
gpointer ptr = NULL;
int type = GRETL_OBJ_EQN;
fname = xmlGetProp(cur, (XUC) "fname");
if (fname == NULL) {
err = 1;
} else {
name = xmlGetProp(cur, (XUC) "name");
if (name == NULL) {
err = 1;
}
}
if (!err) {
session_file_make_path(fullname, (const char *) fname);
gretl_xml_get_prop_as_int(cur, "type", &type);
fprintf(stderr, "model file: fname='%s', type=%d\n", fullname, type);
ptr = rebuild_session_model(fullname, type, &flags, &err);
}
if (!err) {
fprintf(stderr, "reattaching model to session\n");
err = reattach_model(ptr, type, (const char *) name, flags);
if (!err) {
model_count_plus();
}
}
free(fname);
free(name);
cur = cur->next;
i++;
}
#if SESSION_DEBUG
fprintf(stderr, "restore_session_models: returning %d\n", err);
#endif
return err;
}
static int
read_session_xml (const char *fname, struct sample_info *sinfo)
{
xmlDocPtr doc = NULL;
xmlNodePtr cur = NULL;
xmlChar *tmp;
int err = 0;
LIBXML_TEST_VERSION
xmlKeepBlanksDefault(0);
err = gretl_xml_open_doc_root(fname, "gretl-session", &doc, &cur);
if (err) {
gui_errmsg(err);
return 1;
}
/* Now walk the tree */
cur = cur->xmlChildrenNode;
while (cur != NULL && !err) {
if (!xmlStrcmp(cur->name, (XUC) "sample")) {
tmp = xmlGetProp(cur, (XUC) "t1");
if (tmp != NULL) {
sinfo->t1 = atoi((const char *) tmp);
free(tmp);
} else {
err = 1;
}
tmp = xmlGetProp(cur, (XUC) "t2");
if (tmp != NULL) {
sinfo->t2 = atoi((const char *) tmp);
free(tmp);
} else {
err = 1;
}
} else if (!xmlStrcmp(cur->name, (XUC) "submask")) {
err = data_submask_from_xml(cur, doc, sinfo);
} else if (!xmlStrcmp(cur->name, (XUC) "models")) {
tmp = xmlGetProp(cur, (XUC) "count");
if (tmp != NULL) {
session.nmodels = atoi((const char *) tmp);
free(tmp);
if (session.nmodels > 0) {
err = restore_session_models(cur, doc);
}
}
} else if (!xmlStrcmp(cur->name, (XUC) "graphs")) {
tmp = xmlGetProp(cur, (XUC) "count");
if (tmp != NULL) {
session.ngraphs = atoi((const char *) tmp);
free(tmp);
if (session.ngraphs > 0) {
err = restore_session_graphs(cur);
}
}
} else if (!xmlStrcmp(cur->name, (XUC) "texts")) {
tmp = xmlGetProp(cur, (XUC) "count");
if (tmp != NULL) {
session.ntexts = atoi((const char *) tmp);
free(tmp);
if (session.ntexts > 0) {
err = restore_session_texts(cur, doc);
}
}
} else if (!xmlStrcmp(cur->name, (XUC) "notes")) {
session.notes =
(char *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
if (session.notes == NULL) {
err = 1;
}
}
if (!err) {
cur = cur->next;
}
}
if (doc != NULL) {
xmlFreeDoc(doc);
xmlCleanupParser();
}
return err;
}
static int maybe_read_matrix_file (const char *fname)
{
FILE *fp;
fp = gretl_fopen(fname, "r");
if (fp == NULL) {
/* nothing to be read */
return 0;
}
fclose(fp);
return load_user_matrix_file(fname);
}
static int maybe_read_functions_file (const char *fname)
{
FILE *fp;
fp = gretl_fopen(fname, "r");
if (fp == NULL) {
/* nothing to be read */
return 0;
}
fclose(fp);
return read_session_functions_file(fname);
}
static int maybe_read_lists_file (const char *fname)
{
FILE *fp;
fp = gretl_fopen(fname, "r");
if (fp == NULL) {
/* nothing to be read */
return 0;
}
fclose(fp);
return load_user_lists_file(fname);
}
static int model_in_session (const void *ptr)
{
int i;
for (i=0; i<session.nmodels; i++) {
if (session.models[i]->ptr == ptr) {
return 1;
}
}
return 0;
}
static SavedObjectFlags model_save_flags (const void *ptr,
GretlObjType type)
{
SavedObjectFlags flags = 0;
if (model_in_session(ptr)) {
flags |= IN_GUI_SESSION;
}
if (object_is_on_stack(ptr)) {
flags |= IN_NAMED_STACK;
}
if (get_last_model(NULL) == ptr) {
flags |= IS_LAST_MODEL;
}
if (type == GRETL_OBJ_EQN && in_model_table(ptr)) {
flags |= IN_MODEL_TABLE;
}
return flags;
}
static int maybe_write_matrix_file (void)
{
char fullname[MAXLEN];
FILE *fp;
if (n_user_matrices() == 0) {
return 0;
}
session_file_make_path(fullname, "matrices.xml");
fp = gretl_fopen(fullname, "w");
if (fp == NULL) {
return E_FOPEN;
}
write_matrices_to_file(fp);
fclose(fp);
return 0;
}
static int maybe_write_function_file (void)
{
char fullname[MAXLEN];
session_file_make_path(fullname, "functions.xml");
return write_user_function_file(fullname);
}
static int maybe_write_lists_file (void)
{
char fullname[MAXLEN];
session_file_make_path(fullname, "lists.xml");
return gretl_serialize_lists(fullname);
}
static int write_session_xml (void)
{
MODEL *pmod;
char fname[MAXLEN];
char tmpname[MAXLEN];
FILE *fp, *fq;
int nmodels;
int tabmodels;
int i, err = 0;
chdir(paths.userdir);
sprintf(fname, "%s%csession.xml", session.dirname, SLASH);
fp = gretl_fopen(fname, "w");
if (fp == NULL) {
errbox("Couldn't write session file");
return E_FOPEN;
}
gretl_xml_header(fp);
fputs("<gretl-session>\n", fp);
fprintf(fp, " <sample t1=\"%d\" t2=\"%d\"/>\n", datainfo->t1, datainfo->t2);
write_datainfo_submask(datainfo, fp);
nmodels = session.nmodels;
tabmodels = model_table_n_models();
for (i=0; i<tabmodels; i++) {
pmod = model_table_model_by_index(i);
if (!model_in_session(pmod)) {
nmodels++;
}
}
fprintf(fp, " <models count=\"%d\">\n", nmodels);
for (i=0; i<session.nmodels && !err; i++) {
int type = session.models[i]->type;
void *ptr = session.models[i]->ptr;
SavedObjectFlags sflags;
sprintf(tmpname, "%s%cmodel.%d", session.dirname, SLASH, i+1);
fq = fopen(tmpname, "w");
if (fq == NULL) {
errbox("Couldn't write session model file");
err = E_FOPEN;
} else {
sprintf(tmpname, "model.%d", i + 1);
fprintf(fp, " <session-model name=\"%s\" fname=\"%s\" type=\"%d\"/>\n",
session.models[i]->name, tmpname, type);
gretl_xml_header(fq);
sflags = model_save_flags(ptr, type);
if (type == GRETL_OBJ_EQN) {
gretl_model_serialize(ptr, sflags, fq);
} else if (type == GRETL_OBJ_VAR) {
gretl_VAR_serialize(ptr, sflags, fq);
} else if (type == GRETL_OBJ_SYS) {
gretl_system_serialize(ptr, sflags, fq);
}
fclose(fq);
}
}
for (i=0; i<tabmodels && !err; i++) {
pmod = model_table_model_by_index(i);
if (!model_in_session(pmod)) {
sprintf(tmpname, "%s%cmodel.%d", session.dirname, SLASH, i+1);
fq = fopen(tmpname, "w");
if (fq == NULL) {
errbox("Couldn't write session model file");
err = E_FOPEN;
} else {
sprintf(tmpname, "model.%d", i+1);
fprintf(fp, " <session-model name=\"%s\" fname=\"%s\" type=\"%d\"/>\n",
(pmod->name != NULL)? pmod->name : "none", tmpname,
GRETL_OBJ_EQN);
gretl_xml_header(fq);
gretl_model_serialize(pmod, model_save_flags(pmod, GRETL_OBJ_EQN),
fq);
fclose(fq);
}
}
}
if (err) {
fclose(fp);
remove(fname);
return err;
}
fputs(" </models>\n", fp);
fprintf(fp, " <graphs count=\"%d\">\n", session.ngraphs);
for (i=0; i<session.ngraphs; i++) {
fprintf(fp, " <session-graph name=\"%s\" fname=\"%s\" "
"ID=\"%d\" type=\"%d\"",
session.graphs[i]->name, session.graphs[i]->fname,
session.graphs[i]->ID, session.graphs[i]->type);
if (in_graph_page(session.graphs[i]->fname)) {
fputs(" inpage=\"1\"/>\n", fp);
} else {
fputs("/>\n", fp);
}
}
fputs(" </graphs>\n", fp);
fprintf(fp, " <texts count=\"%d\">\n", session.ntexts);
for (i=0; i<session.ntexts; i++) {
fprintf(fp, " <session-text name=\"%s\">", session.texts[i]->name);
gretl_xml_put_raw_string(session.texts[i]->buf, fp);
fputs("</session-text>\n", fp);
}
fputs(" </texts>\n", fp);
if (session.notes != NULL) {
fputs("<notes>", fp);
gretl_xml_put_raw_string(session.notes, fp);
fputs("</notes>\n", fp);
}
fputs("</gretl-session>\n", fp);
fclose(fp);
maybe_write_matrix_file();
maybe_write_function_file();
maybe_write_lists_file();
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1