/* 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; iptr == 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("\n", fp); fprintf(fp, " \n", datainfo->t1, datainfo->t2); write_datainfo_submask(datainfo, fp); nmodels = session.nmodels; tabmodels = model_table_n_models(); for (i=0; i\n", nmodels); for (i=0; itype; 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, " \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\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(" \n", fp); fprintf(fp, " \n", session.ngraphs); for (i=0; iname, 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(" \n", fp); fprintf(fp, " \n", session.ntexts); for (i=0; i", session.texts[i]->name); gretl_xml_put_raw_string(session.texts[i]->buf, fp); fputs("\n", fp); } fputs(" \n", fp); if (session.notes != NULL) { fputs("", fp); gretl_xml_put_raw_string(session.notes, fp); fputs("\n", fp); } fputs("\n", fp); fclose(fp); maybe_write_matrix_file(); maybe_write_function_file(); maybe_write_lists_file(); return 0; }