Files
c-automates-giiiiive/Aloyse et Vincent/printing.c
2024-12-16 02:48:28 +01:00

303 lines
8.1 KiB
C

#include "printing.h"
#include <sys/utsname.h>
#define LINUX_VIEW_COMMAND "| convert - -resize 70% sixel:- | cat"
#define OSX_VIEW_COMMAND "| ./imgcat -W auto"
static char *view_command(void) {
struct utsname name;
uname(&name);
if (strcmp(name.sysname, "Darwin") == 0) {
return OSX_VIEW_COMMAND;
}
else {
return LINUX_VIEW_COMMAND;
}
}
bool external_viewer = false;
/**********************/
/* Printing functions */
/**********************/
// Print d'un sommet, version noms contenus dans un deq
void list_print_state(void *p, FILE *out) {
if (isempty_dequeue(p)) {
fprintf(out, "E");
}
else {
for (uint j = 0; j < size_dequeue(p) - 1; j++) {
fprintf(out, "%d,", lefread_dequeue(p, j));
}
fprintf(out, "%d", lefread_dequeue(p, size_dequeue(p) - 1));
}
}
/********************************/
/* Print des arêtes d'un graphe */
/********************************/
void named_lgedges_print(stack *theedges, nfa *A, FILE *out) {
for (uint i = 0; i < size_stack(theedges); i++) { // Boucle sur les états de départ
fprintf(out, "%d -> %d [label = \"",
((multi_edge *)read_stack(theedges, i))->in,
((multi_edge *)read_stack(theedges, i))->out);
if (!isempty_dequeue(((multi_edge *)read_stack(theedges, i))->lab)) {
for (uint j = 0;
j < size_dequeue(((multi_edge *)read_stack(theedges, i))->lab) - 1;
j++) {
uint letnum =
lefread_dequeue(((multi_edge *)read_stack(theedges, i))->lab, j);
if (A->alpha_names[letnum] == ' ') {
fprintf(out, "%s,", "");
}
else if (A->alpha_names[letnum] == '\"') {
fprintf(out, "\\\",");
}
else {
fprintf(out, "%c,", A->alpha_names[letnum]);
}
}
uint letnum = lefread_dequeue(
((multi_edge *)read_stack(theedges, i))->lab,
size_dequeue(((multi_edge *)read_stack(theedges, i))->lab) - 1);
if (A->alpha_names[letnum] == ' ') {
fprintf(out, "%s\"]\n", "");
}
else if (A->alpha_names[letnum] == '\"') {
fprintf(out, "\\\"\"]\n");
}
else {
fprintf(out, "%c\"]\n", A->alpha_names[letnum]);
}
}
}
}
/******************/
/* Print d'un NFA */
/******************/
bool nfa_print(nfa *A, FILE *out) {
fprintf(out, "digraph {\n");
fprintf(out, "gradientangle=90\n");
fprintf(out, "fontname=\"Helvetica,Arial,sans-serif\"\n");
fprintf(out, "resolution= \"200.0,0.0\"\n");
fprintf(out, "node [fontname=\"Helvetica,Arial,sans-serif\"]\n");
fprintf(out, "edge [fontname=\"Helvetica,Arial,sans-serif\"]\n");
fprintf(out, "rankdir=LR;\n\n");
uint i = 0;
uint f = 0;
for (uint k = 0; k < A->trans->size_graph; k++) {
fprintf(out, "%d [style=solid", k);
if (A->state_names) {
fprintf(out, ",label=\"%s\"", A->state_names[k]);
}
if ((i < size_dequeue(A->initials) &&
lefread_dequeue(A->initials, i) == k) &&
(f < size_dequeue(A->finals) && lefread_dequeue(A->finals, f) == k)) {
fprintf(
out,
",fillcolor=\"blue:green\",style=filled,shape = doublecircle];\n");
i++;
f++;
continue;
}
if (i < size_dequeue(A->initials) && lefread_dequeue(A->initials, i) == k) {
fprintf(out, ",fillcolor=\"blue:green\",style=filled,shape = circle];\n");
i++;
continue;
}
if (f < size_dequeue(A->finals) && lefread_dequeue(A->finals, f) == k) {
fprintf(out, ",shape = doublecircle];\n");
f++;
continue;
}
fprintf(out, ",shape = circle];\n");
}
stack *theedges;
// Calcul de l'ensemble de transitions
theedges = lgraph_to_multi_edges(A->trans);
if (!theedges) {
fprintf(stderr, "Error when printing: unable to convert graph to "
"multi_edges.\nPlease implement lgraph_to_multi_edges().");
return false;
}
named_lgedges_print(theedges, A, out);
while (!isempty_stack(theedges)) {
multi_edge *new = pop(theedges);
delete_dequeue(new->lab);
free(new);
}
delete_stack(theedges);
fprintf(out, "}\n");
return true;
}
/**************************/
/* Affichage sur le shell */
/**************************/
// Affichage d'un NFA
void nfa_view(nfa *thenfa) {
if (!thenfa) {
CRITICAL("NFA is NULL, impossible to display it.");
return;
}
char tmp_filename[] = "/tmp/nfa-XXXXXX.dot";
int d = mkostemps(tmp_filename, 4, O_APPEND);
char png_filename[1 + strlen(tmp_filename)];
strcpy(png_filename, tmp_filename);
strcpy(png_filename + strlen(tmp_filename) - 3, "png");
FILE *f_tmp = fdopen(d, "w");
if (!f_tmp) {
CRITICAL("Unable to open temporary file");
}
nfa_print(thenfa, f_tmp);
fclose(f_tmp);
char *command;
if (!external_viewer) {
command = multiple_strcat("dot -Tpng ", tmp_filename, view_command(), NULL);
}
else {
command = multiple_strcat("dot -Tpng ", tmp_filename, " -o ", png_filename,
"&& open ", png_filename, NULL);
}
TRACE("%s", command);
system(command);
free(command);
}
// Affichage de regexp, pour le débogage.
// Ces fonctions vous sont fournies pour vous aider à déboguer votre code.
static void reg_print_helper(regexp *r, regelem parent) {
TRACE("reg_print_helper");
if (r == NULL) {
return;
}
switch (r->op) {
case CHAR:
if (r->letter == ' ') {
fprintf(stdout, "%s", "");
}
else {
fprintf(stdout, "%c", r->letter);
}
break;
case EMPTY:
print_color("", BLUE, stdout);
break;
case EPSILON:
print_color("ε", YELLOW, stdout);
break;
case UNION:
DEBUG("Union");
if (parent != UNION && parent != NONE) {
print_color("(", CYAN, stdout);
}
reg_print_helper(r->left, UNION);
print_color(" + ", RED, stdout);
reg_print_helper(r->right, UNION);
if (parent != UNION && parent != NONE) {
print_color(")", CYAN, stdout);
}
break;
case INTER:
if (parent != INTER && parent != NONE) {
print_color("(", CYAN, stdout);
}
reg_print_helper(r->left, INTER);
printf("");
reg_print_helper(r->right, INTER);
if (parent != INTER && parent != NONE) {
print_color(")", CYAN, stdout);
}
break;
case CONCAT:
DEBUG("Concat");
if (parent != CONCAT && parent != UNION && parent != NONE) {
print_color("(", CYAN, stdout);
}
reg_print_helper(r->left, CONCAT);
reg_print_helper(r->right, CONCAT);
if (parent != CONCAT && parent != UNION && parent != NONE) {
print_color(")", CYAN, stdout);
}
break;
case STAR:
DEBUG("Star");
if (r->left->op == CHAR || r->left->op == EPSILON || r->left->op == EMPTY) {
reg_print_helper(r->left, STAR);
print_color("*", CYAN, stdout);
}
else {
// printf("(");
reg_print_helper(r->left, STAR);
// printf(")");
print_color("*", CYAN, stdout);
}
break;
case COMPLEMENT:
if (parent != NONE) {
print_color("(", CYAN, stdout);
}
print_color("¬", RED, stdout);
reg_print_helper(r->left, COMPLEMENT);
if (parent != NONE) {
print_color(")", CYAN, stdout);
}
break;
default:
CRITICAL("Unknown regexp operator (%d)", r->op);
break;
}
}
void reg_print(regexp *r) {
TRACE("reg_print");
reg_print_helper(r, NONE);
printf("\n");
}