/***********************/ /* Gestion de fichiers */ /***********************/ #include "files.h" static void reg_to_string_aux(regexp *r, char *buffer) { TRACE("reg_to_string_aux"); if (r == NULL) { return; } switch (r->op) { case CHAR: { char mess[2]; mess[0] = r->letter; mess[1] = '\0'; strcat(buffer, mess); } break; case EMPTY: strcat(buffer, "0"); break; case EPSILON: strcat(buffer, "1"); break; case UNION: strcat(buffer, "("); reg_to_string_aux(r->left, buffer); strcat(buffer, " + "); reg_to_string_aux(r->right, buffer); strcat(buffer, ")"); break; case INTER: strcat(buffer, "("); reg_to_string_aux(r->left, buffer); strcat(buffer, " & "); reg_to_string_aux(r->right, buffer); strcat(buffer, ")"); break; case CONCAT: strcat(buffer, "("); reg_to_string_aux(r->left, buffer); strcat(buffer, " "); reg_to_string_aux(r->right, buffer); strcat(buffer, ")"); break; case STAR: strcat(buffer, "("); reg_to_string_aux(r->left, buffer); strcat(buffer, ")*"); break; case COMPLEMENT: strcat(buffer, "!("); reg_to_string_aux(r->left, buffer); strcat(buffer, ")"); break; default: CRITICAL("Unknown regexp operator (%d)", r->op); break; } } void reg_to_string(regexp *r, char *buffer) { TRACE("reg_to_string"); if (!r) { return; } reg_to_string_aux(r, buffer); } unsigned short autocount = 0; /***********************************************/ /* Manipulation de structures JSON - Automates */ /***********************************************/ json_object *files_auto_to_json(automata *theauto) { // Création de l'objet json json_object *root = json_object_new_object(); if (!root) { fprintf(stderr, "Failed to create the JSON object.\n"); return NULL; } json_object_object_add(root, "TYPE", json_object_new_string("AUTO")); nfa *A = theauto->nfa; // Taille de l'alphabet json_object_object_add(root, "N_ALPH", json_object_new_int(A->trans->size_alpha)); // Taille de l'automate (nombre d'états) json_object_object_add(root, "N_SIZE", json_object_new_int(A->trans->size_graph)); // Alphabet char *alphabet; MALLOC(alphabet, A->trans->size_alpha + 1); for (uint i = 0; i < A->trans->size_alpha; i++) { alphabet[i] = A->alpha_names[i]; } alphabet[A->trans->size_alpha] = '\0'; json_object_object_add(root, "L_ALPH", json_object_new_string(alphabet)); free(alphabet); // Liste des transitions (on commence par compter le nombre de transitions) uint num_trans = 0; for (uint q = 0; q < A->trans->size_graph; q++) { for (uint a = 0; a < A->trans->size_alpha; a++) { num_trans = num_trans + size_dequeue(A->trans->edges[q][a]); } } json_object *trans = json_object_new_array_ext(num_trans); for (uint q = 0; q < A->trans->size_graph; q++) { for (uint a = 0; a < A->trans->size_alpha; a++) { for (uint i = 0; i < size_dequeue(A->trans->edges[q][a]); i++) { json_object *onetrans = json_object_new_array_ext(3); json_object_array_add(onetrans, json_object_new_int(q)); json_object_array_add(onetrans, json_object_new_int(a)); json_object_array_add(onetrans, json_object_new_int(lefread_dequeue( A->trans->edges[q][a], i))); json_object_array_add(trans, onetrans); } } } json_object_object_add(root, "L_TRAN", trans); // Liste des états initiaux json_object *initials = json_object_new_array_ext(size_dequeue(A->initials)); for (uint i = 0; i < size_dequeue(A->initials); i++) { json_object_array_add(initials, json_object_new_int(lefread_dequeue(A->initials, i))); } json_object_object_add(root, "L_INIT", initials); // Liste des états finaux json_object *finals = json_object_new_array_ext(size_dequeue(A->finals)); for (uint i = 0; i < size_dequeue(A->finals); i++) { json_object_array_add(finals, json_object_new_int(lefread_dequeue(A->finals, i))); } json_object_object_add(root, "L_FINA", finals); return root; } json_object *files_lang_to_json(language *thelang) { json_object *root = json_object_new_object(); if (!root) { fprintf(stderr, "Failed to create the JSON object.\n"); return NULL; } json_object_object_add(root, "TYPE", json_object_new_string("LANG")); if (thelang->type == SPE_REG) { json_object_object_add(root, "SPEC", json_object_new_string("REXP")); char *newexp; MALLOC(newexp, EXPSIZE); newexp[0] = 0; reg_to_string(thelang->reg, newexp); json_object_object_add(root, "REXP", json_object_new_string(newexp)); free(newexp); } if (thelang->type == SPE_NFA) { json_object_object_add(root, "SPEC", json_object_new_string("AUTO")); json_object_object_add(root, "AUTO", files_auto_to_json(objects[thelang->nfa]->aut)); } return root; } nfa *files_json_to_nfa(json_object *root) { // Récupération de la taille de l'automate json_object *jsize_graph; if (!json_object_object_get_ex(root, "N_SIZE", &jsize_graph) || json_object_get_type(jsize_graph) != json_type_int) { fprintf(stderr, "Error: cannot read the size of the automaton.\n"); return NULL; } uint size_graph = json_object_get_int(jsize_graph); // Récupération de la taille de l'alphabet json_object *jsize_alpha; if (!json_object_object_get_ex(root, "N_ALPH", &jsize_alpha) || json_object_get_type(jsize_alpha) != json_type_int) { fprintf(stderr, "Error: cannot read the size of the alphabet.\n"); return NULL; } uint size_alpha = json_object_get_int(jsize_alpha); // Création du NFA nfa *A; MALLOC(A, 1); MALLOC(A->alpha_names, size_alpha); A->trans = create_lgraph_noedges(size_graph, size_alpha); if (A->trans == NULL) { fprintf(stderr, "Error: cannot create the transitions\nPlease implement " "the function create_lgraph_noedges\n"); free(A->alpha_names); free(A); return NULL; } A->initials = create_dequeue(); if (A->initials == NULL) { fprintf(stderr, "Error: cannot create the initials\nPlease implement the " "function create_dequeue\n"); free(A->alpha_names); free(A); return NULL; } A->finals = create_dequeue(); A->state_names = NULL; // Récupération de l'alphabet json_object *jalph; if (!json_object_object_get_ex(root, "L_ALPH", &jalph) || json_object_get_type(jalph) != json_type_string) { fprintf(stderr, "Error: cannot read the alphabet.\n"); nfa_delete(A); return NULL; } const char *alphabet = json_object_get_string(jalph); for (uint i = 0; i < size_alpha; i++) { A->alpha_names[i] = alphabet[i]; } // Récupération du graphe des transitions json_object *jtrans; if (!json_object_object_get_ex(root, "L_TRAN", &jtrans) || json_object_get_type(jtrans) != json_type_array) { fprintf(stderr, "Error: cannot read the list of transitions.\n"); nfa_delete(A); return NULL; } uint len = json_object_array_length(jtrans); for (uint i = 0; i < len; i++) { json_object *onetrans = json_object_array_get_idx(jtrans, i); if (json_object_get_type(onetrans) != json_type_array || json_object_array_length(onetrans) != 3) { fprintf(stderr, "Error: cannot read the list of transitions.\n"); nfa_delete(A); return NULL; } json_object *jq = json_object_array_get_idx(onetrans, 0); json_object *ja = json_object_array_get_idx(onetrans, 1); json_object *jr = json_object_array_get_idx(onetrans, 2); if (json_object_get_type(jq) != json_type_int || json_object_get_type(jr) != json_type_int) { fprintf(stderr, "Error: cannot read the list of transitions.\n"); nfa_delete(A); return NULL; } uint q = json_object_get_int(jq); uint r = json_object_get_int(jr); uint a; if (json_object_get_type(ja) == json_type_int) { a = json_object_get_int(ja); } else if (json_object_get_type(ja) == json_type_string && json_object_get_string_len(ja) == 1) { const char *sa = json_object_get_string(ja); a = sa[0]; int id = -1; for (uint j = 0; j < size_alpha; j++) { if (a == (uint)A->alpha_names[j]) { id = j; } } if (id >= 0) { a = (uint)id; } else { fprintf(stderr, "Error: incorrect letter used in the transitions.\n"); nfa_delete(A); return NULL; } } else { fprintf(stderr, "Error: cannot read the list of transitions.\n"); nfa_delete(A); return NULL; } if (q < size_graph && r < size_graph && a < size_alpha) { rigins_dequeue(r, A->trans->edges[q][a]); } else { fprintf(stderr, "Error: incorrect letter or state used in the transitions.\n"); nfa_delete(A); return NULL; } } for (uint q = 0; q < size_graph; q++) { for (uint a = 0; a < size_alpha; a++) { sort_dequeue_norepeat(A->trans->edges[q][a]); } } // Récupération de la liste des états initiaux A->initials = create_dequeue(); json_object *jini; if (!json_object_object_get_ex(root, "L_INIT", &jini) || json_object_get_type(jini) != json_type_array) { fprintf(stderr, "Error: cannot read the list of initial states.\n"); nfa_delete(A); return NULL; } len = json_object_array_length(jini); for (uint i = 0; i < len; i++) { json_object *jq = json_object_array_get_idx(jini, i); if (json_object_get_type(jq) != json_type_int) { fprintf(stderr, "Error: cannot read the list of final states.\n"); nfa_delete(A); return NULL; } uint q = json_object_get_int(jq); if (q < size_graph) { rigins_dequeue(q, A->initials); } else { fprintf(stderr, "Error: incorrect state in the list of initial states.\n"); nfa_delete(A); return NULL; } } sort_dequeue_norepeat(A->initials); // Récupération de la liste des états finaux A->finals = create_dequeue(); json_object *jfin; if (!json_object_object_get_ex(root, "L_FINA", &jfin) || json_object_get_type(jfin) != json_type_array) { fprintf(stderr, "Error: cannot read the list of final states.\n"); nfa_delete(A); return NULL; } len = json_object_array_length(jfin); for (uint i = 0; i < len; i++) { json_object *jq = json_object_array_get_idx(jfin, i); if (json_object_get_type(jq) != json_type_int) { fprintf(stderr, "Error: cannot read the list of final states.\n"); nfa_delete(A); return NULL; } uint q = json_object_get_int(jq); if (q < size_graph) { rigins_dequeue(q, A->finals); } else { fprintf(stderr, "Error: incorrect state in the list of final states.\n"); nfa_delete(A); return NULL; } } sort_dequeue_norepeat(A->finals); return A; } /************************************/ /* Lecture/écriture dans un fichier */ /************************************/ void files_save_object(object *theobj, char *filename) { json_object *root = NULL; switch (theobj->type) { case LANGUAGE: root = files_lang_to_json(theobj->lan); break; case AUTOMATON: root = files_auto_to_json(theobj->aut); break; default: return; break; } // Sauvegarde if (json_object_to_file(filename, root)) { fprintf(stderr, "Error: failed to save %s.\n", filename); } else { printf("%s saved.\n", filename); } // Libération du JSON json_object_put(root); } static void files_read_object_aux(json_object *root, char *varname) { json_object *obj_type; if (!json_object_object_get_ex(root, "TYPE", &obj_type) || json_object_get_type(obj_type) != json_type_string) { fprintf(stderr, "Error: cannot read the type of the object.\n"); return; } const char *thetype = json_object_get_string(obj_type); if (strcmp(thetype, "AUTO") == 0) { fprintf(stdout, "Reading an automaton.\n"); nfa *A = files_json_to_nfa(root); object_add_automata(varname, A); return; } if (strcmp(thetype, "LANG") == 0) { fprintf(stdout, "Reading a language.\n"); json_object *lang_spe; if (!json_object_object_get_ex(root, "SPEC", &lang_spe) || json_object_get_type(lang_spe) != json_type_string) { fprintf(stderr, "Error: cannot read the specification type of the language.\n"); return; } const char *thespec = json_object_get_string(lang_spe); if (strcmp(thespec, "REXP") == 0) { json_object *theregexp; if (!json_object_object_get_ex(root, "REXP", &theregexp) || json_object_get_type(theregexp) != json_type_string) { fprintf(stderr, "Error: cannot read the regular expression specifying " "the language.\n"); return; } const char *exp = json_object_get_string(theregexp); regexp *myexp = parse_string_regexp(exp); if (myexp == NULL) { return; } reg_print(myexp); object_add_language_reg(varname, myexp); } if (strcmp(thespec, "AUTO") == 0) { json_object *theauto; if (!json_object_object_get_ex(root, "AUTO", &theauto) || json_object_get_type(theauto) != json_type_object) { fprintf(stderr, "Error: cannot read the automaton specifying the language.\n"); return; } nfa *A = files_json_to_nfa(theauto); char *newname; MALLOC(newname, 20); sprintf(newname, "SYSAUTO%04d", autocount++); int j = object_add_automata(newname, A); object_add_language_nfa(varname, j); return; } return; } } void files_read_object(char *filename, char *varname) { json_object *root = json_object_from_file(filename); if (!root) { fprintf(stderr, "Failed to read the file.\n"); return; } files_read_object_aux(root, varname); json_object_put(root); return; } void files_save_session(char *filename) { // Création de l'objet json json_object *root = json_object_new_object(); if (!root) { fprintf(stderr, "Failed to create the JSON object.\n"); return; } json_object_object_add(root, "TYPE", json_object_new_string("SESSION")); uint size = 0; for (int i = 0; i < nb_objects; i++) { { if (objects[i]->parent == -1) { size++; } } } json_object *thetable = json_object_new_array_ext(size); for (int i = 0; i < nb_objects; i++) { if (objects[i]->parent == -1) { json_object *oneobj = json_object_new_array_ext(2); json_object_array_add(oneobj, json_object_new_string(objects[i]->name)); if (objects[i]->type == LANGUAGE) { json_object_array_add(oneobj, files_lang_to_json(objects[i]->lan)); } if (objects[i]->type == AUTOMATON) { json_object_array_add(oneobj, files_auto_to_json(objects[i]->aut)); } json_object_array_add(thetable, oneobj); } } json_object_object_add(root, "OBJS", thetable); // Sauvegarde if (json_object_to_file(filename, root)) { fprintf(stderr, "Error: failed to save %s.\n", filename); } else { printf("%s saved.\n", filename); } // Libération du JSON json_object_put(root); } void files_load_session(char *filename) { json_object *root = json_object_from_file(filename); if (!root) { fprintf(stderr, "Failed to read the file.\n"); return; } // Récupération du type json_object *obj_type; if (!json_object_object_get_ex(root, "TYPE", &obj_type) || json_object_get_type(obj_type) != json_type_string) { fprintf(stderr, "Error: cannot read the type of the object.\n"); return; } const char *thetype = json_object_get_string(obj_type); if (strcmp(thetype, "SESSION") != 0) { fprintf(stderr, "Error: not a session file.\n"); return; } // Récupération des objets json_object *jobjs; if (!json_object_object_get_ex(root, "OBJS", &jobjs) || json_object_get_type(jobjs) != json_type_array) { fprintf(stderr, "Error: cannot read the list of objects.\n"); return; } uint len = json_object_array_length(jobjs); for (uint i = 0; i < len; i++) { json_object *oneobj = json_object_array_get_idx(jobjs, i); if (json_object_get_type(oneobj) != json_type_array || json_object_array_length(oneobj) != 2) { fprintf(stderr, "Error: cannot read the list of objects.\n"); return; } json_object *varname = json_object_array_get_idx(oneobj, 0); json_object *theobje = json_object_array_get_idx(oneobj, 1); const char *thename = json_object_get_string(varname); files_read_object_aux(theobje, strdup(thename)); } json_object_put(root); }