From efbcadeca72dc339802e1760db7f8336bd20f514 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Sat, 13 Jun 2020 16:03:53 +0200 Subject: [PATCH] reports: don't escape the labels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we use "quotearg" to escape the strings output in Dot. As a result, if the user's locale is C for instance, all the non-ASCII are escaped. Unfortunately graphviz does not interpret this style of escaping. For instance: 5 -> 2 [style=solid label="\"\303\221\303\271\341\271\203\303\251\342\204\235\303\264\""] was displayed as a sequence of numbers. We now output: 5 -> 2 [style=solid label="\"Ñùṃéℝô\""] independently of the user's locale. * src/system.h (obstack_backslash): New. * src/graphviz.h, src/graphviz.c (escape): Remove, use obstack_backslash instead. * src/print-graph.c: Likewise. * tests/report.at: Adjust. --- src/graphviz.c | 22 ++++++++++++---------- src/graphviz.h | 6 ------ src/print-graph.c | 19 ++++++++++++++----- src/system.h | 17 +++++++++++++++++ tests/report.at | 32 ++++++++++++++++---------------- 5 files changed, 59 insertions(+), 37 deletions(-) diff --git a/src/graphviz.c b/src/graphviz.c index 80a2ff99..34d80b03 100644 --- a/src/graphviz.c +++ b/src/graphviz.c @@ -72,18 +72,20 @@ output_edge (int source, int destination, char const *label, { fprintf (fout, " %d -> %d [style=%s", source, destination, style); if (label) - fprintf (fout, " label=%s", quote (label)); + { + fputs (" label=\"", fout); + for (const char *cp = label; *cp; ++cp) + switch (*cp) + { + case '"': fputs ("\\\"", fout); break; + case '\\': fputs ("\\\\", fout); break; + default: fputc (*cp, fout); break; + } + fputc ('"', fout); + } fputs ("]\n", fout); } -char const * -escape (char const *name) -{ - char *q = quote (name); - q[strlen (q) - 1] = '\0'; - return q + 1; -} - static void no_reduce_bitset_init (state const *s, bitset *no_reduce_set) { @@ -149,7 +151,7 @@ print_token (struct obstack *out, bool first, char const *tok) { if (! first) obstack_sgrow (out, ", "); - obstack_sgrow (out, escape (tok)); + obstack_backslash (out, tok); return false; } diff --git a/src/graphviz.h b/src/graphviz.h index 06b42358..ead22ffd 100644 --- a/src/graphviz.h +++ b/src/graphviz.h @@ -63,10 +63,4 @@ void output_red (state const *s, reductions const *reds, FILE *fout); */ void finish_graph (FILE *fout); -/** Escape a lookahead token. - * - * \param name the token. - */ -char const *escape (char const *name); - #endif /* ! GRAPHVIZ_H_ */ diff --git a/src/print-graph.c b/src/print-graph.c index 5691c6d8..adaa8bed 100644 --- a/src/print-graph.c +++ b/src/print-graph.c @@ -72,19 +72,28 @@ print_core (struct obstack *oout, state *s) obstack_printf (oout, "%*s| ", (int) strlen (previous_lhs->symbol->tag), ""); else - obstack_printf (oout, "%s: ", escape (r->lhs->symbol->tag)); + { + obstack_backslash (oout, r->lhs->symbol->tag); + obstack_printf (oout, ": "); + } previous_lhs = r->lhs; for (item_number const *sp = r->rhs; sp < sp1; sp++) - obstack_printf (oout, "%s ", escape (symbols[*sp]->tag)); + { + obstack_backslash (oout, symbols[*sp]->tag); + obstack_1grow (oout, ' '); + } obstack_1grow (oout, '.'); if (0 <= *r->rhs) for (item_number const *sp = sp1; 0 <= *sp; ++sp) - obstack_printf (oout, " %s", escape (symbols[*sp]->tag)); + { + obstack_1grow (oout, ' '); + obstack_backslash (oout, symbols[*sp]->tag); + } else - obstack_printf (oout, " %%empty"); + obstack_sgrow (oout, " %empty"); /* Experimental feature: display the lookahead tokens. */ if (report_flag & report_lookahead_tokens @@ -104,7 +113,7 @@ print_core (struct obstack *oout, state *s) BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0) { obstack_sgrow (oout, sep); - obstack_sgrow (oout, escape (symbols[k]->tag)); + obstack_backslash (oout, symbols[k]->tag); sep = ", "; } obstack_1grow (oout, ']'); diff --git a/src/system.h b/src/system.h index 33986069..eac89c27 100644 --- a/src/system.h +++ b/src/system.h @@ -171,6 +171,23 @@ typedef size_t uintptr_t; # define obstack_sgrow(Obs, Str) \ obstack_grow (Obs, Str, strlen (Str)) +/* Output Str escaped to be a string. + + For instance "\"foo\"" -> "\\\"foo\\\"". */ + +# define obstack_backslash(Obs, Str) \ + do { \ + char const *p__; \ + for (p__ = Str; *p__; p__++) \ + switch (*p__) \ + { \ + case '"': obstack_sgrow (Obs, "\\\""); break; \ + case '\\': obstack_sgrow (Obs, "\\\\"); break; \ + default: obstack_1grow (Obs, *p__); break; \ + } \ + } while (0) + + /* Output Str escaped for our postprocessing (i.e., escape M4 special characters). diff --git a/tests/report.at b/tests/report.at index c83d1704..27d4e7b8 100644 --- a/tests/report.at +++ b/tests/report.at @@ -1338,43 +1338,43 @@ digraph "input.y" node [fontname = courier, shape = box, colorscheme = paired6] edge [fontname = courier] - 0 [label="State 0\n\l 0 $accept: . exp $end\l 1 exp: . exp \"\342\212\225\" exp\l 2 | . exp \"+\" exp\l 3 | . exp \"+\" exp\l 4 | . \"number\"\l 5 | . \"\303\221\303\271\341\271\203\303\251\342\204\235\303\264\"\l"] + 0 [label="State 0\n\l 0 $accept: . exp $end\l 1 exp: . exp \"⊕\" exp\l 2 | . exp \"+\" exp\l 3 | . exp \"+\" exp\l 4 | . \"number\"\l 5 | . \"Ñùṃéℝô\"\l"] 0 -> 1 [style=solid label="\"number\""] - 0 -> 2 [style=solid label="\"\303\221\303\271\341\271\203\303\251\342\204\235\303\264\""] + 0 -> 2 [style=solid label="\"Ñùṃéℝô\""] 0 -> 3 [style=dashed label="exp"] 1 [label="State 1\n\l 4 exp: \"number\" .\l"] 1 -> "1R4" [style=solid] "1R4" [label="R4", fillcolor=3, shape=diamond, style=filled] - 2 [label="State 2\n\l 5 exp: \"\303\221\303\271\341\271\203\303\251\342\204\235\303\264\" .\l"] + 2 [label="State 2\n\l 5 exp: \"Ñùṃéℝô\" .\l"] 2 -> "2R5" [style=solid] "2R5" [label="R5", fillcolor=3, shape=diamond, style=filled] - 3 [label="State 3\n\l 0 $accept: exp . $end\l 1 exp: exp . \"\342\212\225\" exp\l 2 | exp . \"+\" exp\l 3 | exp . \"+\" exp\l"] + 3 [label="State 3\n\l 0 $accept: exp . $end\l 1 exp: exp . \"⊕\" exp\l 2 | exp . \"+\" exp\l 3 | exp . \"+\" exp\l"] 3 -> 4 [style=solid label="$end"] 3 -> 5 [style=solid label="\"+\""] - 3 -> 6 [style=solid label="\"\342\212\225\""] + 3 -> 6 [style=solid label="\"⊕\""] 4 [label="State 4\n\l 0 $accept: exp $end .\l"] 4 -> "4R0" [style=solid] "4R0" [label="Acc", fillcolor=1, shape=diamond, style=filled] - 5 [label="State 5\n\l 1 exp: . exp \"\342\212\225\" exp\l 2 | . exp \"+\" exp\l 2 | exp \"+\" . exp\l 3 | . exp \"+\" exp\l 3 | exp \"+\" . exp\l 4 | . \"number\"\l 5 | . \"\303\221\303\271\341\271\203\303\251\342\204\235\303\264\"\l"] + 5 [label="State 5\n\l 1 exp: . exp \"⊕\" exp\l 2 | . exp \"+\" exp\l 2 | exp \"+\" . exp\l 3 | . exp \"+\" exp\l 3 | exp \"+\" . exp\l 4 | . \"number\"\l 5 | . \"Ñùṃéℝô\"\l"] 5 -> 1 [style=solid label="\"number\""] - 5 -> 2 [style=solid label="\"\303\221\303\271\341\271\203\303\251\342\204\235\303\264\""] + 5 -> 2 [style=solid label="\"Ñùṃéℝô\""] 5 -> 7 [style=dashed label="exp"] - 6 [label="State 6\n\l 1 exp: . exp \"\342\212\225\" exp\l 1 | exp \"\342\212\225\" . exp\l 2 | . exp \"+\" exp\l 3 | . exp \"+\" exp\l 4 | . \"number\"\l 5 | . \"\303\221\303\271\341\271\203\303\251\342\204\235\303\264\"\l"] + 6 [label="State 6\n\l 1 exp: . exp \"⊕\" exp\l 1 | exp \"⊕\" . exp\l 2 | . exp \"+\" exp\l 3 | . exp \"+\" exp\l 4 | . \"number\"\l 5 | . \"Ñùṃéℝô\"\l"] 6 -> 1 [style=solid label="\"number\""] - 6 -> 2 [style=solid label="\"\303\221\303\271\341\271\203\303\251\342\204\235\303\264\""] + 6 -> 2 [style=solid label="\"Ñùṃéℝô\""] 6 -> 8 [style=dashed label="exp"] - 7 [label="State 7\n\l 1 exp: exp . \"\342\212\225\" exp\l 2 | exp . \"+\" exp\l 2 | exp \"+\" exp . [$end, \"+\", \"\342\212\225\"]\l 3 | exp . \"+\" exp\l 3 | exp \"+\" exp . [$end, \"+\", \"\342\212\225\"]\l"] - 7 -> 6 [style=solid label="\"\342\212\225\""] - 7 -> "7R2d" [label="[\"\342\212\225\"]", style=solid] + 7 [label="State 7\n\l 1 exp: exp . \"⊕\" exp\l 2 | exp . \"+\" exp\l 2 | exp \"+\" exp . [$end, \"+\", \"⊕\"]\l 3 | exp . \"+\" exp\l 3 | exp \"+\" exp . [$end, \"+\", \"⊕\"]\l"] + 7 -> 6 [style=solid label="\"⊕\""] + 7 -> "7R2d" [label="[\"⊕\"]", style=solid] "7R2d" [label="R2", fillcolor=5, shape=diamond, style=filled] 7 -> "7R2" [style=solid] "7R2" [label="R2", fillcolor=3, shape=diamond, style=filled] - 7 -> "7R3d" [label="[$end, \"+\", \"\342\212\225\"]", style=solid] + 7 -> "7R3d" [label="[$end, \"+\", \"⊕\"]", style=solid] "7R3d" [label="R3", fillcolor=5, shape=diamond, style=filled] - 8 [label="State 8\n\l 1 exp: exp . \"\342\212\225\" exp\l 1 | exp \"\342\212\225\" exp . [$end, \"+\", \"\342\212\225\"]\l 2 | exp . \"+\" exp\l 3 | exp . \"+\" exp\l"] + 8 [label="State 8\n\l 1 exp: exp . \"⊕\" exp\l 1 | exp \"⊕\" exp . [$end, \"+\", \"⊕\"]\l 2 | exp . \"+\" exp\l 3 | exp . \"+\" exp\l"] 8 -> 5 [style=solid label="\"+\""] - 8 -> 6 [style=solid label="\"\342\212\225\""] - 8 -> "8R1d" [label="[\"+\", \"\342\212\225\"]", style=solid] + 8 -> 6 [style=solid label="\"⊕\""] + 8 -> "8R1d" [label="[\"+\", \"⊕\"]", style=solid] "8R1d" [label="R1", fillcolor=5, shape=diamond, style=filled] 8 -> "8R1" [style=solid] "8R1" [label="R1", fillcolor=3, shape=diamond, style=filled]